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