|
| 1 | +import type { EndpointParameters } from "./server/endpoints/endpoints"; |
1 | 2 | import type { BackendModel } from "./server/models";
|
2 |
| -import type { Message } from "./types/Message"; |
3 |
| -import { format } from "date-fns"; |
4 |
| -import type { WebSearch } from "./types/WebSearch"; |
5 |
| -import { downloadFile } from "./server/files/downloadFile"; |
6 |
| -import type { Conversation } from "./types/Conversation"; |
7 | 3 |
|
8 |
| -interface buildPromptOptions { |
9 |
| - messages: Pick<Message, "from" | "content" | "files">[]; |
10 |
| - id?: Conversation["_id"]; |
| 4 | +type buildPromptOptions = Pick<EndpointParameters, "messages" | "preprompt" | "continueMessage"> & { |
11 | 5 | model: BackendModel;
|
12 |
| - locals?: App.Locals; |
13 |
| - webSearch?: WebSearch; |
14 |
| - preprompt?: string; |
15 |
| - files?: File[]; |
16 |
| - continue?: boolean; |
17 |
| -} |
| 6 | +}; |
18 | 7 |
|
19 | 8 | export async function buildPrompt({
|
20 | 9 | messages,
|
21 | 10 | model,
|
22 |
| - webSearch, |
23 | 11 | preprompt,
|
24 |
| - id, |
| 12 | + continueMessage, |
25 | 13 | }: buildPromptOptions): Promise<string> {
|
26 |
| - let modifiedMessages = [...messages]; |
27 |
| - |
28 |
| - if (webSearch && webSearch.context) { |
29 |
| - // find index of the last user message |
30 |
| - const lastUsrMsgIndex = modifiedMessages.map((el) => el.from).lastIndexOf("user"); |
31 |
| - |
32 |
| - // combine all the other previous questions into one string |
33 |
| - const previousUserMessages = modifiedMessages.filter((el) => el.from === "user").slice(0, -1); |
34 |
| - const previousQuestions = |
35 |
| - previousUserMessages.length > 0 |
36 |
| - ? `Previous questions: \n${previousUserMessages |
37 |
| - .map(({ content }) => `- ${content}`) |
38 |
| - .join("\n")}` |
39 |
| - : ""; |
40 |
| - |
41 |
| - const currentDate = format(new Date(), "MMMM d, yyyy"); |
42 |
| - |
43 |
| - // update the last user message directly (that way if the last message is an assistant partial answer, we keep the beginning of that answer) |
44 |
| - modifiedMessages[lastUsrMsgIndex] = { |
45 |
| - from: "user", |
46 |
| - content: `I searched the web using the query: ${webSearch.searchQuery}. Today is ${currentDate} and here are the results: |
47 |
| -===================== |
48 |
| -${webSearch.context} |
49 |
| -===================== |
50 |
| -${previousQuestions} |
51 |
| -Answer the question: ${messages[lastUsrMsgIndex].content}`, |
52 |
| - }; |
53 |
| - } |
54 |
| - // section to handle potential files input |
55 |
| - if (model.multimodal) { |
56 |
| - modifiedMessages = await Promise.all( |
57 |
| - modifiedMessages.map(async (el) => { |
58 |
| - let content = el.content; |
59 |
| - |
60 |
| - if (el.from === "user") { |
61 |
| - if (el?.files && el.files.length > 0 && id) { |
62 |
| - const markdowns = await Promise.all( |
63 |
| - el.files.map(async (hash) => { |
64 |
| - try { |
65 |
| - const { content: image, mime } = await downloadFile(hash, id); |
66 |
| - const b64 = image.toString("base64"); |
67 |
| - return `})`; |
68 |
| - } catch (e) { |
69 |
| - console.error(e); |
70 |
| - } |
71 |
| - }) |
72 |
| - ); |
73 |
| - content += markdowns.join("\n "); |
74 |
| - } else { |
75 |
| - // if no image, append an empty white image |
76 |
| - content += |
77 |
| - "\n"; |
78 |
| - } |
79 |
| - } |
80 |
| - |
81 |
| - return { ...el, content }; |
82 |
| - }) |
83 |
| - ); |
| 14 | + let prompt = model |
| 15 | + .chatPromptRender({ messages, preprompt }) |
| 16 | + // Not super precise, but it's truncated in the model's backend anyway |
| 17 | + .split(" ") |
| 18 | + .slice(-(model.parameters?.truncate ?? 0)) |
| 19 | + .join(" "); |
| 20 | + |
| 21 | + if (continueMessage && model.parameters?.stop) { |
| 22 | + prompt = model.parameters.stop.reduce((acc: string, curr: string) => { |
| 23 | + if (acc.endsWith(curr)) { |
| 24 | + return acc.slice(0, acc.length - curr.length); |
| 25 | + } |
| 26 | + return acc; |
| 27 | + }, prompt.trimEnd()); |
84 | 28 | }
|
85 | 29 |
|
86 |
| - return ( |
87 |
| - model |
88 |
| - .chatPromptRender({ messages: modifiedMessages, preprompt }) |
89 |
| - // Not super precise, but it's truncated in the model's backend anyway |
90 |
| - .split(" ") |
91 |
| - .slice(-(model.parameters?.truncate ?? 0)) |
92 |
| - .join(" ") |
93 |
| - ); |
| 30 | + return prompt; |
94 | 31 | }
|
0 commit comments