From 5b64ae1efc3b6101b67a950a49aef3de7875af73 Mon Sep 17 00:00:00 2001 From: henri123lemoine Date: Fri, 31 Mar 2023 21:45:15 -0400 Subject: [PATCH 1/8] Reduced odds of context length error. --- api/chat.py | 117 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/api/chat.py b/api/chat.py index 2254223..be2c1a2 100644 --- a/api/chat.py +++ b/api/chat.py @@ -14,87 +14,108 @@ MODERATION_ENDPOINT = "https://api.openai.com/v1/moderations" # OpenAI parameters LEN_EMBEDDINGS = 1536 -MAX_TOKEN_LEN_PROMPT = 4095 # This may be 8191, unsure. -TRUNCATE_CONTEXT = 2000 +MAX_TOKEN_LEN_PROMPT = 8191 if COMPLETIONS_MODEL == 'gpt-4' else 4095 +TRUNCATE_CONTEXT_LEN = 1500 +TRUNCATE_HISTORY_LEN = 500 +MAX_RESPONSE_LEN = 900 -# --------------------------------- prompt code -------------------------------- +# -------------------------------- prompt code -------------------------------- def limit_tokens(text: str, max_tokens: int, encoding_name: str = "cl100k_base") -> str: encoding = tiktoken.get_encoding(encoding_name) tokens = encoding.encode(text)[:max_tokens] return encoding.decode(tokens) -def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Block]) -> List[Dict[str, str]]: - # History takes the format: history=[ - # {"role": "system", "content": "You are a helpful assistant."}, - # {"role": "user", "content": "Who won the world series in 2020?"}, - # {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, - # {"role": "user", "content": "Where was it played?"} - # {"role": "assistant", "content": "Los Angeles, California."} - # ] - - # Initialize prompt with system description - prompt = [{"role": "system", "content": "You are a helpful assistant knowledgeable about AI Alignment and Safety."}] - - # Add previous dialogue - prompt.extend(history) - - instruction_prompt = \ +def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Block], encoding_name: str = "cl100k_base") -> List[Dict[str, str]]: + # Encoder to count tokens + enc = tiktoken.get_encoding(encoding_name) + total_tokens = 0 + + prompt = [] + + system_prompt = "You are a helpful assistant knowledgeable about AI Alignment. You are provided with a question and a set of sources. Your job is to answer the question using the sources, and cite the sources you use." + total_tokens += len(enc.encode(system_prompt)) + + # Get past user queries + past_user_queries = "\n".join([message["content"] for message in history if message["role"] == "user"][-5:-1]) + past_queries_prompt = f"My previous queries were:\n{past_user_queries}" + + # Instruction prompt + instruction_context_query_prompt = \ "Please give a clear and coherent answer to my question (written after \"Q:\") " \ "using the following sources. Each source is labeled with a letter. Feel free to " \ "use the sources in any order, and try to use multiple sources in your answer." - prompt.append({"role": "user", "content": instruction_prompt}) - - # Add context from top-k blocks + # Context from top-k blocks context_prompt = "" for i, block in enumerate(context): context_prompt += f"[{chr(ord('a') + i)}] {block.title} - {block.author} - {block.date}\n\n{block.text}\n\n\n" - context_prompt = context_prompt[:-2] # trim last two newlines - - context_prompt = limit_tokens(context_prompt, TRUNCATE_CONTEXT) # truncate to about 2k tokens - - prompt.append({"role": "user", "content": f"{context_prompt}"}) + context_prompt = limit_tokens(context_prompt, TRUNCATE_CONTEXT_LEN) # truncate the context_prompt to max TRUNCATE_CONTEXT tokens + context_prompt += "\n" if (context_prompt[-1] != "\n") else "" - # Add user query - question_prompt = "In your answer, please cite any claims you make back to each source " \ - "using the format: [a], [b], etc. If you use multiple sources to make a claim " \ - "cite all of them. For example: \"AGI is concerning [c, d, e].\"" + # Question prompt + question_prompt = f"In your answer, please cite any claims you make back to each source " \ + f"using the format: [a], [b], etc. If you use multiple sources to make a claim " \ + f"cite all of them. For example: \"AGI is concerning [c, d, e].\"" \ + f"" \ + f"" \ + f"Q: {query}" - question_prompt += "\n\n\nQ: " + query - - prompt.append({"role": "user", "content": question_prompt}) + instruction_context_query_prompt = f"{instruction_context_query_prompt}\n\n{context_prompt}\n\n{question_prompt}" - return prompt - - - + total_tokens += len(enc.encode(past_queries_prompt)) + total_tokens += len(enc.encode(history[-2]["content"])) # Get past user query + total_tokens += len(enc.encode(history[-1]["content"])) + total_tokens += len(enc.encode(instruction_context_query_prompt)) + + # If the prompt is too long, truncate the last answer + if total_tokens > MAX_TOKEN_LEN_PROMPT - TRUNCATE_HISTORY_LEN: + tokens_left = MAX_TOKEN_LEN_PROMPT - total_tokens + print(f"WARNING: Prompt is too long! Prompt length: {total_tokens} tokens") + last_assistant_reply_trunctated = limit_tokens(prompt[-1]["content"], tokens_left) + prompt[-1]["content"] = f"{last_assistant_reply_trunctated}" + + prompt.append({"role": "system", "content": system_prompt}) + prompt.append({"role": "user", "content": past_queries_prompt}) + prompt.extend(history[-2:]) + prompt.append({"role": "user", "content": instruction_context_query_prompt}) + + return prompt, MAX_TOKEN_LEN_PROMPT - (total_tokens + 50) # add 50 tokens for safety # ------------------------------------------------------------------------------ - -def normal_completion(prompt: List[Dict[str, str]]) -> str: + +def normal_completion(prompt: List[Dict[str, str]], max_tokens_completion: int) -> str: try: return openai.ChatCompletion.create( model=COMPLETIONS_MODEL, - messages=prompt - )["choices"][0]["message"]["content"] + messages=prompt, + max_tokens=max_tokens_completion + )["choices"][0]["text"] except Exception as e: print(e) return "I'm sorry, I failed to process your query. Please try again. If the problem persists, please contact the administrator." -# returns either (True, reply string, embeddings) or (False, error message string, None) + def talk_to_robot(dataset_dict, query: str, history: List[Dict[str, str]] = [], k: int = 10): # 1. Find the most relevant blocks from the Alignment Research Dataset top_k_blocks: List[Block] = get_top_k_blocks(dataset_dict, query, k) # 2. Generate a prompt for the ChatCompletions API - prompt: List[Dict[str, str]] = construct_prompt(query, history, top_k_blocks) - - # if we were to error out, return something like this - # return (False, "Example error message", None) + prompt, max_tokens_completion = construct_prompt(query, history, top_k_blocks) # 3. Answer the user query - return (True, normal_completion(prompt), top_k_blocks) + return (normal_completion(prompt, max_tokens_completion), top_k_blocks) + + +if __name__ == "__main__": + import config + openai.api_key = config.OPENAI_API_KEY + completion = openai.ChatCompletion.create( + model=COMPLETIONS_MODEL, + messages=[ + {"role": "system", "content": "?" * 8 * 2045}, + ] + ) \ No newline at end of file From 219de8fd3cb11d05544b3f9858971d687d71cd2c Mon Sep 17 00:00:00 2001 From: Fraser Date: Fri, 31 Mar 2023 22:00:57 -0400 Subject: [PATCH 2/8] pad body --- api/get_blocks.py | 14 +++++++++++++- web/src/styles/globals.css | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/api/get_blocks.py b/api/get_blocks.py index 6f30cb1..965d41f 100644 --- a/api/get_blocks.py +++ b/api/get_blocks.py @@ -47,13 +47,25 @@ def get_embedding(text: str) -> np.ndarray: # Get the k blocks most semantically similar to the query. def get_top_k_blocks(data, user_query: str, k: int = 10) -> List[Block]: + # print time + t = time.time() + # Get the embedding for the query. query_embedding = get_embedding(user_query) - + + t1 = time.time() + print("Time to get embedding: ", t1 - t) + similarity_scores = np.dot(data["embeddings"], query_embedding) # big fat calculation + + t2 = time.time() + print("Time to get similarity scores: ", t2 - t1) top_k_block_indices = list(reversed(np.argpartition(similarity_scores, -k)[-k:])) # Get the top k indices of the blocks + t3 = time.time() + print("Time to get top k indices: ", t3 - t2) + top_k_metadata_indexes = [data["embeddings_metadata_index"][i] for i in top_k_block_indices] top_k_texts = [strip_block(data["embedding_strings"][i]) for i in top_k_block_indices] top_k_metadata = [data["metadata"][i] for i in top_k_metadata_indexes] diff --git a/web/src/styles/globals.css b/web/src/styles/globals.css index 2e88fa2..f304db2 100644 --- a/web/src/styles/globals.css +++ b/web/src/styles/globals.css @@ -15,6 +15,8 @@ main { max-width: 800px; margin: 0 auto; padding: 0 2rem; + margin-top: 4rem; + margin-bottom: 4rem; } a { From 1dbb24e30a852b76c0a7326d8fd76ff1b06bd5b9 Mon Sep 17 00:00:00 2001 From: Fraser Date: Fri, 31 Mar 2023 22:05:20 -0400 Subject: [PATCH 3/8] limit to a max of 3 blocks from any one source --- api/get_blocks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/get_blocks.py b/api/get_blocks.py index 965d41f..d4af74e 100644 --- a/api/get_blocks.py +++ b/api/get_blocks.py @@ -88,6 +88,8 @@ def get_top_k_blocks(data, user_query: str, k: int = 10) -> List[Block]: for key, group in itertools.groupby(blocks_plus_old_index, key=key): group = list(group) if len(group) == 0: continue + + group = group[:3] # limit to a max of 3 blocks from any one source text = "\n\n\n.....\n\n\n".join([block[0].text for block in group]) From b197ee086ccecc3005590afee0ff70ac9b325eb9 Mon Sep 17 00:00:00 2001 From: henri123lemoine Date: Fri, 31 Mar 2023 22:10:53 -0400 Subject: [PATCH 4/8] Big fix total_tokens --- api/chat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/chat.py b/api/chat.py index be2c1a2..4b570e0 100644 --- a/api/chat.py +++ b/api/chat.py @@ -65,8 +65,8 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl instruction_context_query_prompt = f"{instruction_context_query_prompt}\n\n{context_prompt}\n\n{question_prompt}" total_tokens += len(enc.encode(past_queries_prompt)) - total_tokens += len(enc.encode(history[-2]["content"])) # Get past user query - total_tokens += len(enc.encode(history[-1]["content"])) + total_tokens += len(enc.encode(history[-2]["content"])) if (len(history) >= 2) else 0 + total_tokens += len(enc.encode(history[-1]["content"])) if (len(history) >= 1) else 0 total_tokens += len(enc.encode(instruction_context_query_prompt)) # If the prompt is too long, truncate the last answer From 26f7d4411e64866d5f959c993967859627c6a613 Mon Sep 17 00:00:00 2001 From: Fraser Date: Fri, 31 Mar 2023 22:57:00 -0400 Subject: [PATCH 5/8] get chat slightly more compiling --- .gitignore | 3 +++ api/chat.py | 47 ++++++++++++++++++++++------------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 4f9ddb1..3d798c6 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,6 @@ src/tmp.py .vercel/ api/dataset.pkl +temp/ + +api/dataset_big.pkl diff --git a/api/chat.py b/api/chat.py index 4b570e0..7270b98 100644 --- a/api/chat.py +++ b/api/chat.py @@ -19,26 +19,34 @@ TRUNCATE_CONTEXT_LEN = 1500 TRUNCATE_HISTORY_LEN = 500 MAX_RESPONSE_LEN = 900 -# -------------------------------- prompt code -------------------------------- +# --------------------------------- prompt code -------------------------------- def limit_tokens(text: str, max_tokens: int, encoding_name: str = "cl100k_base") -> str: encoding = tiktoken.get_encoding(encoding_name) tokens = encoding.encode(text)[:max_tokens] return encoding.decode(tokens) -def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Block], encoding_name: str = "cl100k_base") -> List[Dict[str, str]]: +def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Block], encoding_name: str = "cl100k_base"): + # History takes the format: history=[ + # {"role": "system", "content": "You are a helpful assistant."}, + # {"role": "user", "content": "Who won the world series in 2020?"}, + # {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}, + # {"role": "user", "content": "Where was it played?"} + # {"role": "assistant", "content": "Los Angeles, California."} + # ] + # Encoder to count tokens enc = tiktoken.get_encoding(encoding_name) total_tokens = 0 prompt = [] - system_prompt = "You are a helpful assistant knowledgeable about AI Alignment. You are provided with a question and a set of sources. Your job is to answer the question using the sources, and cite the sources you use." + system_prompt = "You are a helpful assistant knowledgeable about AI Alignment and Saftey." total_tokens += len(enc.encode(system_prompt)) # Get past user queries - past_user_queries = "\n".join([message["content"] for message in history if message["role"] == "user"][-5:-1]) - past_queries_prompt = f"My previous queries were:\n{past_user_queries}" + past_user_queries = "\nQ: ".join([message["content"] for message in history if message["role"] == "user"][-5:]) + past_user_queries = f"My previous queries in our conversation have been:\n" + past_user_queries # Instruction prompt instruction_context_query_prompt = \ @@ -48,6 +56,7 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl # Context from top-k blocks context_prompt = "" + for i, block in enumerate(context): context_prompt += f"[{chr(ord('a') + i)}] {block.title} - {block.author} - {block.date}\n\n{block.text}\n\n\n" context_prompt = context_prompt[:-2] # trim last two newlines @@ -57,14 +66,11 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl # Question prompt question_prompt = f"In your answer, please cite any claims you make back to each source " \ f"using the format: [a], [b], etc. If you use multiple sources to make a claim " \ - f"cite all of them. For example: \"AGI is concerning [c, d, e].\"" \ - f"" \ - f"" \ - f"Q: {query}" + f"cite all of them. For example: \"AGI is concerning [c, d, e].\"\n\nQ: " + query instruction_context_query_prompt = f"{instruction_context_query_prompt}\n\n{context_prompt}\n\n{question_prompt}" - total_tokens += len(enc.encode(past_queries_prompt)) + total_tokens += len(enc.encode(past_user_queries)) total_tokens += len(enc.encode(history[-2]["content"])) if (len(history) >= 2) else 0 total_tokens += len(enc.encode(history[-1]["content"])) if (len(history) >= 1) else 0 total_tokens += len(enc.encode(instruction_context_query_prompt)) @@ -77,7 +83,7 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl prompt[-1]["content"] = f"{last_assistant_reply_trunctated}" prompt.append({"role": "system", "content": system_prompt}) - prompt.append({"role": "user", "content": past_queries_prompt}) + prompt.append({"role": "user", "content": past_user_queries}) prompt.extend(history[-2:]) prompt.append({"role": "user", "content": instruction_context_query_prompt}) @@ -96,7 +102,7 @@ def normal_completion(prompt: List[Dict[str, str]], max_tokens_completion: int) print(e) return "I'm sorry, I failed to process your query. Please try again. If the problem persists, please contact the administrator." - +# returns either (True, reply string, embeddings) or (False, error message string, None) def talk_to_robot(dataset_dict, query: str, history: List[Dict[str, str]] = [], k: int = 10): # 1. Find the most relevant blocks from the Alignment Research Dataset @@ -104,18 +110,9 @@ def talk_to_robot(dataset_dict, query: str, history: List[Dict[str, str]] = [], # 2. Generate a prompt for the ChatCompletions API prompt, max_tokens_completion = construct_prompt(query, history, top_k_blocks) + + # if we were to error out, return something like this + # return (False, "Example error message", None) # 3. Answer the user query - return (normal_completion(prompt, max_tokens_completion), top_k_blocks) - - -if __name__ == "__main__": - import config - openai.api_key = config.OPENAI_API_KEY - - completion = openai.ChatCompletion.create( - model=COMPLETIONS_MODEL, - messages=[ - {"role": "system", "content": "?" * 8 * 2045}, - ] - ) \ No newline at end of file + return (True, normal_completion(prompt, max_tokens_completion), top_k_blocks) From 74fa2b7b1ad982203687463b6a50774bbb142b22 Mon Sep 17 00:00:00 2001 From: Fraser Date: Fri, 31 Mar 2023 23:19:22 -0400 Subject: [PATCH 6/8] fix bug --- api/chat.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/api/chat.py b/api/chat.py index 7270b98..11d18d9 100644 --- a/api/chat.py +++ b/api/chat.py @@ -38,16 +38,16 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl # Encoder to count tokens enc = tiktoken.get_encoding(encoding_name) total_tokens = 0 - + prompt = [] - + system_prompt = "You are a helpful assistant knowledgeable about AI Alignment and Saftey." total_tokens += len(enc.encode(system_prompt)) - + # Get past user queries past_user_queries = "\nQ: ".join([message["content"] for message in history if message["role"] == "user"][-5:]) past_user_queries = f"My previous queries in our conversation have been:\n" + past_user_queries - + # Instruction prompt instruction_context_query_prompt = \ "Please give a clear and coherent answer to my question (written after \"Q:\") " \ @@ -62,32 +62,32 @@ def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Bl context_prompt = context_prompt[:-2] # trim last two newlines context_prompt = limit_tokens(context_prompt, TRUNCATE_CONTEXT_LEN) # truncate the context_prompt to max TRUNCATE_CONTEXT tokens context_prompt += "\n" if (context_prompt[-1] != "\n") else "" - + # Question prompt question_prompt = f"In your answer, please cite any claims you make back to each source " \ f"using the format: [a], [b], etc. If you use multiple sources to make a claim " \ f"cite all of them. For example: \"AGI is concerning [c, d, e].\"\n\nQ: " + query instruction_context_query_prompt = f"{instruction_context_query_prompt}\n\n{context_prompt}\n\n{question_prompt}" - + total_tokens += len(enc.encode(past_user_queries)) total_tokens += len(enc.encode(history[-2]["content"])) if (len(history) >= 2) else 0 total_tokens += len(enc.encode(history[-1]["content"])) if (len(history) >= 1) else 0 total_tokens += len(enc.encode(instruction_context_query_prompt)) - + # If the prompt is too long, truncate the last answer if total_tokens > MAX_TOKEN_LEN_PROMPT - TRUNCATE_HISTORY_LEN: tokens_left = MAX_TOKEN_LEN_PROMPT - total_tokens print(f"WARNING: Prompt is too long! Prompt length: {total_tokens} tokens") last_assistant_reply_trunctated = limit_tokens(prompt[-1]["content"], tokens_left) prompt[-1]["content"] = f"{last_assistant_reply_trunctated}" - + prompt.append({"role": "system", "content": system_prompt}) prompt.append({"role": "user", "content": past_user_queries}) prompt.extend(history[-2:]) prompt.append({"role": "user", "content": instruction_context_query_prompt}) - - return prompt, MAX_TOKEN_LEN_PROMPT - (total_tokens + 50) # add 50 tokens for safety + + return prompt, MAX_TOKEN_LEN_PROMPT - (total_tokens + 50) # add 50 tokens for safety # ------------------------------------------------------------------------------ @@ -97,7 +97,7 @@ def normal_completion(prompt: List[Dict[str, str]], max_tokens_completion: int) model=COMPLETIONS_MODEL, messages=prompt, max_tokens=max_tokens_completion - )["choices"][0]["text"] + )["choices"][0]["message"]["content"] except Exception as e: print(e) return "I'm sorry, I failed to process your query. Please try again. If the problem persists, please contact the administrator." From d49e18d4d0dc4767b3f9ef5a81a19c749e47e001 Mon Sep 17 00:00:00 2001 From: Fraser Date: Sat, 1 Apr 2023 01:20:59 -0400 Subject: [PATCH 7/8] add gpt 4 toggle --- .gitignore | 2 ++ api/chat.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3d798c6..df62ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -140,3 +140,5 @@ api/dataset.pkl temp/ api/dataset_big.pkl + +api/dataset_300.pkl diff --git a/api/chat.py b/api/chat.py index 11d18d9..67d7589 100644 --- a/api/chat.py +++ b/api/chat.py @@ -10,12 +10,13 @@ import tiktoken # OpenAI models EMBEDDING_MODEL = "text-embedding-ada-002" COMPLETIONS_MODEL = "gpt-3.5-turbo" +# COMPLETIONS_MODEL = "gpt-4" MODERATION_ENDPOINT = "https://api.openai.com/v1/moderations" # OpenAI parameters LEN_EMBEDDINGS = 1536 MAX_TOKEN_LEN_PROMPT = 8191 if COMPLETIONS_MODEL == 'gpt-4' else 4095 -TRUNCATE_CONTEXT_LEN = 1500 +TRUNCATE_CONTEXT_LEN = 2300 if COMPLETIONS_MODEL == 'gpt-4' else 1500 TRUNCATE_HISTORY_LEN = 500 MAX_RESPONSE_LEN = 900 @@ -111,6 +112,10 @@ def talk_to_robot(dataset_dict, query: str, history: List[Dict[str, str]] = [], # 2. Generate a prompt for the ChatCompletions API prompt, max_tokens_completion = construct_prompt(query, history, top_k_blocks) + print(" ------------------------------ prompt: -----------------------------") + for message in prompt: + print(f"{message['role']}: {message['content']}\n\n") + # if we were to error out, return something like this # return (False, "Example error message", None) From ebeba0cfbb7a17640c55216492496d6224cb1da9 Mon Sep 17 00:00:00 2001 From: Fraser Date: Sat, 1 Apr 2023 03:22:00 -0400 Subject: [PATCH 8/8] fix margin --- api/chat.py | 7 ++++--- web/src/header.tsx | 2 +- web/src/pages/index.tsx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/chat.py b/api/chat.py index 67d7589..fb5378e 100644 --- a/api/chat.py +++ b/api/chat.py @@ -28,6 +28,7 @@ def limit_tokens(text: str, max_tokens: int, encoding_name: str = "cl100k_base") return encoding.decode(tokens) def construct_prompt(query: str, history: List[Dict[str, str]], context: List[Block], encoding_name: str = "cl100k_base"): + # History takes the format: history=[ # {"role": "system", "content": "You are a helpful assistant."}, # {"role": "user", "content": "Who won the world series in 2020?"}, @@ -112,9 +113,9 @@ def talk_to_robot(dataset_dict, query: str, history: List[Dict[str, str]] = [], # 2. Generate a prompt for the ChatCompletions API prompt, max_tokens_completion = construct_prompt(query, history, top_k_blocks) - print(" ------------------------------ prompt: -----------------------------") - for message in prompt: - print(f"{message['role']}: {message['content']}\n\n") + # print(" ------------------------------ prompt: -----------------------------") + # for message in prompt: + # print(f"{message['role']}: {message['content']}\n\n") # if we were to error out, return something like this # return (False, "Example error message", None) diff --git a/web/src/header.tsx b/web/src/header.tsx index 059a96e..46320a7 100644 --- a/web/src/header.tsx +++ b/web/src/header.tsx @@ -16,7 +16,7 @@ const Header: React.FC<{page: "index" | "semantic"}> = ({page}) => { return (<>
-

Alignment Search

+

AlignmentSearch

{sidebar}

diff --git a/web/src/pages/index.tsx b/web/src/pages/index.tsx index 5a76ec2..dee86c5 100644 --- a/web/src/pages/index.tsx +++ b/web/src/pages/index.tsx @@ -87,7 +87,7 @@ const ShowEntry: React.FC<{entry: Entry}> = ({entry}) => { // system reply return ( -

+
{ // split into paragraphs entry.display_content.split("\n").map(paragraph => (

{ paragraph.split(in_text_citation_regex).map((text, i) => {