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 +1 -1
- src/lib/buildPrompt.ts +13 -3
- src/lib/server/generateFromDefaultEndpoint.ts +1 -0
- src/lib/server/models.ts +1 -14
- src/lib/server/summarize.ts +38 -29
- src/lib/server/websearch/generateQuery.ts +57 -32
- src/lib/types/Template.ts +0 -6
@@ -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}}
|
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,
|
@@ -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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
const currentDate = format(new Date(), "MMMM d, yyyy");
|
29 |
messages = [
|
30 |
...messagesWithoutLastUsrMsg,
|
31 |
{
|
32 |
from: "user",
|
33 |
-
content: `
|
34 |
=====================
|
35 |
${webSearch.context}
|
36 |
=====================
|
37 |
-
|
|
|
|
|
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 |
}
|
@@ -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);
|
@@ -1,5 +1,5 @@
|
|
1 |
import { HF_ACCESS_TOKEN, MODELS, OLD_MODELS, TASK_MODEL } from "$env/static/private";
|
2 |
-
import type { ChatTemplateInput
|
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,
|
@@ -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 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
});
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
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 |
}
|
@@ -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 {
|
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 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
-
|
|
|
|
|
43 |
});
|
44 |
|
45 |
-
return
|
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 |
}
|
@@ -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 |
};
|
|
|
|
|
|
|
|
|
|
|
|