nsarrazin HF staff Mishig victor HF staff commited on
Commit
1e5090f
1 Parent(s): 830b0b6

Update websearch prompting & summary prompting (#503)

Browse files

* Use the task model for websearch query generation

* summary with examples in chat format

* Update to websearch prompting

- Removed web search template
- Added examples in `generateQuery`
- Passed previous questions when generating the web search query
- Added previous questions to the bottom of the context window in `buildPrompt` when using websearch

* wait for model if needed

* rm console.log

* get rid of regex

* added a few time related examples

* Update src/lib/server/websearch/generateQuery.ts

Co-authored-by: Mishig <[email protected]>

* reformat yesterday

* test

* fix whitespace

* remove extra whitespace for mistral

* removed mistral extra whitespace

* Update src/lib/server/summarize.ts

Co-authored-by: Victor Muštar <[email protected]>

* Update src/lib/server/summarize.ts

Co-authored-by: Victor Muštar <[email protected]>

* add an emoji if none is found in the first three characters

---------

Co-authored-by: Mishig <[email protected]>
Co-authored-by: Victor Muštar <[email protected]>

.env.template CHANGED
@@ -99,7 +99,7 @@ MODELS=`[
99
  "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.",
100
  "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/",
101
  "preprompt": "",
102
- "chatPromptTemplate" : "<s>{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}} {{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}</s> {{/ifAssistant}}{{/each}}",
103
  "parameters": {
104
  "temperature": 0.1,
105
  "top_p": 0.95,
 
99
  "description": "Mistral 7B is a new Apache 2.0 model, released by Mistral AI that outperforms Llama2 13B in benchmarks.",
100
  "websiteUrl": "https://mistral.ai/news/announcing-mistral-7b/",
101
  "preprompt": "",
102
+ "chatPromptTemplate" : "<s>{{#each messages}}{{#ifUser}}[INST] {{#if @first}}{{#if @root.preprompt}}{{@root.preprompt}}\n{{/if}}{{/if}}{{content}} [/INST]{{/ifUser}}{{#ifAssistant}}{{content}}</s>{{/ifAssistant}}{{/each}}",
103
  "parameters": {
104
  "temperature": 0.1,
105
  "top_p": 0.95,
src/lib/buildPrompt.ts CHANGED
@@ -23,18 +23,28 @@ export async function buildPrompt({
23
  preprompt,
24
  }: buildPromptOptions): Promise<string> {
25
  if (webSearch && webSearch.context) {
 
26
  const messagesWithoutLastUsrMsg = messages.slice(0, -1);
27
- const lastUserMsg = messages.slice(-1)[0];
 
 
 
 
 
 
 
28
  const currentDate = format(new Date(), "MMMM d, yyyy");
29
  messages = [
30
  ...messagesWithoutLastUsrMsg,
31
  {
32
  from: "user",
33
- content: `Please answer my question "${lastUserMsg.content}" using the supplied context below (paragraphs from various websites). For the context, today is ${currentDate}:
34
  =====================
35
  ${webSearch.context}
36
  =====================
37
- So my question is "${lastUserMsg.content}"`,
 
 
38
  },
39
  ];
40
  }
 
23
  preprompt,
24
  }: buildPromptOptions): Promise<string> {
25
  if (webSearch && webSearch.context) {
26
+ const lastMsg = messages.slice(-1)[0];
27
  const messagesWithoutLastUsrMsg = messages.slice(0, -1);
28
+ const previousUserMessages = messages.filter((el) => el.from === "user").slice(0, -1);
29
+
30
+ const previousQuestions =
31
+ previousUserMessages.length > 0
32
+ ? `Previous questions: \n${previousUserMessages
33
+ .map(({ content }) => `- ${content}`)
34
+ .join("\n")}`
35
+ : "";
36
  const currentDate = format(new Date(), "MMMM d, yyyy");
37
  messages = [
38
  ...messagesWithoutLastUsrMsg,
39
  {
40
  from: "user",
41
+ content: `I searched the web using the query: ${webSearch.searchQuery}. Today is ${currentDate} and here are the results:
42
  =====================
43
  ${webSearch.context}
44
  =====================
45
+ ${previousQuestions}
46
+ Answer the question: ${lastMsg.content}
47
+ `,
48
  },
49
  ];
50
  }
src/lib/server/generateFromDefaultEndpoint.ts CHANGED
@@ -19,6 +19,7 @@ export async function generateFromDefaultEndpoint(
19
  ...smallModel.parameters,
20
  ...parameters,
21
  return_full_text: false,
 
22
  };
23
 
24
  const randomEndpoint = modelEndpoint(smallModel);
 
19
  ...smallModel.parameters,
20
  ...parameters,
21
  return_full_text: false,
22
+ wait_for_model: true,
23
  };
24
 
25
  const randomEndpoint = modelEndpoint(smallModel);
src/lib/server/models.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { HF_ACCESS_TOKEN, MODELS, OLD_MODELS, TASK_MODEL } from "$env/static/private";
2
- import type { ChatTemplateInput, WebSearchQueryTemplateInput } from "$lib/types/Template";
3
  import { compileTemplate } from "$lib/utils/template";
4
  import { z } from "zod";
5
 
@@ -67,15 +67,6 @@ const modelsRaw = z
67
  "{{/each}}" +
68
  "{{assistantMessageToken}}"
69
  ),
70
- webSearchQueryPromptTemplate: z
71
- .string()
72
- .default(
73
- "{{userMessageToken}}" +
74
- 'My question is: "{{message.content}}". ' +
75
- "Based on the conversation history (my previous questions are: {{previousMessages}}), give me an appropriate query to answer my question for google search. You should not say more than query. You should not say any words except the query. For the context, today is {{currentDate}}" +
76
- "{{userMessageEndToken}}" +
77
- "{{assistantMessageToken}}"
78
- ),
79
  promptExamples: z
80
  .array(
81
  z.object({
@@ -104,10 +95,6 @@ export const models = await Promise.all(
104
  userMessageEndToken: m?.userMessageEndToken || m?.messageEndToken,
105
  assistantMessageEndToken: m?.assistantMessageEndToken || m?.messageEndToken,
106
  chatPromptRender: compileTemplate<ChatTemplateInput>(m.chatPromptTemplate, m),
107
- webSearchQueryPromptRender: compileTemplate<WebSearchQueryTemplateInput>(
108
- m.webSearchQueryPromptTemplate,
109
- m
110
- ),
111
  id: m.id || m.name,
112
  displayName: m.displayName || m.name,
113
  preprompt: m.prepromptUrl ? await fetch(m.prepromptUrl).then((r) => r.text()) : m.preprompt,
 
1
  import { HF_ACCESS_TOKEN, MODELS, OLD_MODELS, TASK_MODEL } from "$env/static/private";
2
+ import type { ChatTemplateInput } from "$lib/types/Template";
3
  import { compileTemplate } from "$lib/utils/template";
4
  import { z } from "zod";
5
 
 
67
  "{{/each}}" +
68
  "{{assistantMessageToken}}"
69
  ),
 
 
 
 
 
 
 
 
 
70
  promptExamples: z
71
  .array(
72
  z.object({
 
95
  userMessageEndToken: m?.userMessageEndToken || m?.messageEndToken,
96
  assistantMessageEndToken: m?.assistantMessageEndToken || m?.messageEndToken,
97
  chatPromptRender: compileTemplate<ChatTemplateInput>(m.chatPromptTemplate, m),
 
 
 
 
98
  id: m.id || m.name,
99
  displayName: m.displayName || m.name,
100
  preprompt: m.prepromptUrl ? await fetch(m.prepromptUrl).then((r) => r.text()) : m.preprompt,
src/lib/server/summarize.ts CHANGED
@@ -1,39 +1,48 @@
1
- import { buildPrompt } from "$lib/buildPrompt";
2
- import { generateFromDefaultEndpoint } from "$lib/server/generateFromDefaultEndpoint";
3
- import { defaultModel } from "$lib/server/models";
4
  import { LLM_SUMMERIZATION } from "$env/static/private";
 
 
 
5
 
6
  export async function summarize(prompt: string) {
7
  if (!LLM_SUMMERIZATION) {
8
  return prompt.split(/\s+/g).slice(0, 5).join(" ");
9
  }
10
- const userPrompt = `Please summarize the following message: \n` + prompt;
11
-
12
- const summaryPrompt = await buildPrompt({
13
- messages: [{ from: "user", content: userPrompt }],
14
- preprompt: `
15
- You are a summarization AI. Your task is to summarize user requests, in a single sentence of less than 5 words. Do not try to answer questions, just summarize the user's request. Start your answer with an emoji relevant to the summary."
16
-
17
- Example: "Who is the president of France ?"
18
- Summary: "🇫🇷 President of France request"
19
-
20
- Example: "What are the latest news ?"
21
- Summary: "📰 Latest news"
22
 
23
- Example: "Can you debug this python code?"
24
- Summary: "🐍 Python code debugging request"
25
- `,
26
- model: defaultModel,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  });
28
 
29
- const generated_text = await generateFromDefaultEndpoint(summaryPrompt).catch((e) => {
30
- console.error(e);
31
- return null;
32
- });
33
-
34
- if (generated_text) {
35
- return generated_text;
36
- }
37
-
38
- return null;
 
 
39
  }
 
 
 
 
1
  import { LLM_SUMMERIZATION } from "$env/static/private";
2
+ import { generateFromDefaultEndpoint } from "$lib/server/generateFromDefaultEndpoint";
3
+ import { smallModel } from "$lib/server/models";
4
+ import type { Message } from "$lib/types/Message";
5
 
6
  export async function summarize(prompt: string) {
7
  if (!LLM_SUMMERIZATION) {
8
  return prompt.split(/\s+/g).slice(0, 5).join(" ");
9
  }
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ const messages: Array<Omit<Message, "id">> = [
12
+ { from: "user", content: "Who is the president of Gabon?" },
13
+ { from: "assistant", content: "🇬🇦 President of Gabon" },
14
+ { from: "user", content: "Who is Julien Chaumond?" },
15
+ { from: "assistant", content: "🧑 Julien Chaumond" },
16
+ { from: "user", content: "what is 1 + 1?" },
17
+ { from: "assistant", content: "🔢 Simple math operation" },
18
+ { from: "user", content: "What are the latest news?" },
19
+ { from: "assistant", content: "📰 Latest news" },
20
+ { from: "user", content: "How to make a great cheesecake?" },
21
+ { from: "assistant", content: "🍰 Cheesecake recipe" },
22
+ { from: "user", content: "what is your favorite movie? do a short answer." },
23
+ { from: "assistant", content: "🎥 Favorite movie" },
24
+ { from: "user", content: "Explain the concept of artificial intelligence in one sentence" },
25
+ { from: "assistant", content: "🤖 AI definition" },
26
+ { from: "user", content: "Answer all my questions like chewbacca from now ok?" },
27
+ { from: "assistant", content: "🐒 Answer as Chewbacca" },
28
+ { from: "user", content: prompt },
29
+ ];
30
+
31
+ const summaryPrompt = smallModel.chatPromptRender({
32
+ messages,
33
+ preprompt: `You are a summarization AI. You'll never answer a user's question directly, but instead summarize the user's request into a single short sentence of four words or less. Always start your answer with an emoji relevant to the summary.`,
34
  });
35
 
36
+ return await generateFromDefaultEndpoint(summaryPrompt)
37
+ .then((summary) => {
38
+ // add an emoji if none is found in the first three characters
39
+ if (!/\p{Emoji}/u.test(summary.slice(0, 3))) {
40
+ return "💬 " + summary;
41
+ }
42
+ return summary;
43
+ })
44
+ .catch((e) => {
45
+ console.error(e);
46
+ return null;
47
+ });
48
  }
src/lib/server/websearch/generateQuery.ts CHANGED
@@ -1,46 +1,71 @@
1
  import type { Message } from "$lib/types/Message";
2
  import { format } from "date-fns";
3
  import { generateFromDefaultEndpoint } from "../generateFromDefaultEndpoint";
4
- import { defaultModel } from "../models";
5
 
6
  export async function generateQuery(messages: Message[]) {
7
  const currentDate = format(new Date(), "MMMM d, yyyy");
8
  const userMessages = messages.filter(({ from }) => from === "user");
9
  const previousUserMessages = userMessages.slice(0, -1);
 
10
  const lastMessage = userMessages.slice(-1)[0];
11
- const promptSearchQuery = defaultModel.webSearchQueryPromptRender({
12
- message: lastMessage,
13
- previousMessages: previousUserMessages.map(({ content }) => content).join(" "),
14
- currentDate,
15
- });
16
- const searchQuery = await generateFromDefaultEndpoint(promptSearchQuery).then((query) => {
17
- // example of generating google query:
18
- // case 1
19
- // user: tell me what happened yesterday
20
- // LLM: google query is "news september 12, 2023"
21
- // the regex below will try to capture the last "phrase" (i.e. words between quotes or double quotes or ticks)
22
- // in this case, it is "news september 12, 2023"
23
- // if there is no "phrase", we will just use the user query, which was "tell me what happened yesterday"
24
- const regexLastPhrase = /("|'|`)((?:(?!\1).)+)\1$/;
25
- let match = query.match(regexLastPhrase);
26
- if (match) {
27
- return match[2];
28
- }
29
 
30
- // case 2
31
- // user: tell me what happened yesterday
32
- // LLM: Here is a query: news september 12, 2023
33
- // the regex below will try to capture the last sentences starting from :
34
- // in this case, it is "news september 12, 2023"
35
- // if there is no math, we will just use the user query, which was "tell me what happened yesterday"
36
- const regexColon = /:\s(.*)$/;
37
- match = query.match(regexColon);
38
- if (match) {
39
- return match[1];
40
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- return lastMessage.content;
 
 
43
  });
44
 
45
- return searchQuery;
46
  }
 
1
  import type { Message } from "$lib/types/Message";
2
  import { format } from "date-fns";
3
  import { generateFromDefaultEndpoint } from "../generateFromDefaultEndpoint";
4
+ import { smallModel } from "../models";
5
 
6
  export async function generateQuery(messages: Message[]) {
7
  const currentDate = format(new Date(), "MMMM d, yyyy");
8
  const userMessages = messages.filter(({ from }) => from === "user");
9
  const previousUserMessages = userMessages.slice(0, -1);
10
+
11
  const lastMessage = userMessages.slice(-1)[0];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ const convQuery: Array<Omit<Message, "id">> = [
14
+ {
15
+ from: "user",
16
+ content: `Previous Questions:
17
+ - Who is the president of France?
18
+
19
+ Current Question: What about Mexico?
20
+ `,
21
+ },
22
+ {
23
+ from: "assistant",
24
+ content: "President of Mexico",
25
+ },
26
+ {
27
+ from: "user",
28
+ content: `Previous questions:
29
+ - When is the next formula 1 grand prix?
30
+
31
+ Current Question: Where is it being hosted ?`,
32
+ },
33
+ {
34
+ from: "assistant",
35
+ content: "location of next formula 1 grand prix",
36
+ },
37
+ {
38
+ from: "user",
39
+ content: "Current Question: What type of printhead does the Epson F2270 DTG printer use?",
40
+ },
41
+ {
42
+ from: "assistant",
43
+ content: "Epson F2270 DTG printer printhead",
44
+ },
45
+ { from: "user", content: "What were the news yesterday ?" },
46
+ {
47
+ from: "assistant",
48
+ content: `news ${format(new Date(Date.now() - 864e5), "MMMM d, yyyy")}`,
49
+ },
50
+ { from: "user", content: "What is the current weather in Paris ?" },
51
+ { from: "assistant", content: `weather in Paris ${currentDate}` },
52
+ {
53
+ from: "user",
54
+ content:
55
+ (previousUserMessages.length > 0
56
+ ? `Previous questions: \n${previousUserMessages
57
+ .map(({ content }) => `- ${content}`)
58
+ .join("\n")}`
59
+ : "") +
60
+ "\n\nCurrent Question:" +
61
+ lastMessage.content,
62
+ },
63
+ ];
64
 
65
+ const promptQuery = smallModel.chatPromptRender({
66
+ preprompt: `You are tasked with generating web search queries. Give me an appropriate query to answer my question for google search. Answer with only the query. Today is ${currentDate}`,
67
+ messages: convQuery,
68
  });
69
 
70
+ return await generateFromDefaultEndpoint(promptQuery);
71
  }
src/lib/types/Template.ts CHANGED
@@ -12,9 +12,3 @@ export type ChatTemplateInput = {
12
  messages: Pick<Message, "from" | "content">[];
13
  preprompt?: string;
14
  };
15
-
16
- export type WebSearchQueryTemplateInput = {
17
- message: Pick<Message, "from" | "content">;
18
- previousMessages: string;
19
- currentDate: string;
20
- };
 
12
  messages: Pick<Message, "from" | "content">[];
13
  preprompt?: string;
14
  };