You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
3.3 KiB
TypeScript
102 lines
3.3 KiB
TypeScript
import {
|
|
router,
|
|
publicProcedure,
|
|
createCallerFactory,
|
|
} from "../../trpc/server";
|
|
import { createCaller as createConversationsCaller } from "./conversations.js";
|
|
import { MODEL_NAME, openrouter } from "./provider.js";
|
|
import { generateObject, generateText, jsonSchema } from "ai";
|
|
import type { DraftMessage } from "../../types.js";
|
|
|
|
const runningSummarySystemPrompt = ({
|
|
previousRunningSummary,
|
|
}: {
|
|
previousRunningSummary: string;
|
|
}) => `You are an expert at summarizing conversations.
|
|
|
|
You will be given a summary of a conversation, and the messages exchanged since that summary was produced.
|
|
|
|
Your task is to produce a new summary of the conversation.
|
|
|
|
* The user should be referred to as "the user" in the summary.
|
|
* The user's pronouns should be either he or she, NOT "they" or "them", because this summary will be read by an AI assistant to give it context; and excessive use of "they" or "them" will make what they refer to unclear or ambiguous.
|
|
* The assistant should be referred to as "I" or "me", because this summary will be read by an AI assistant to give it context.
|
|
* The new summary may omit details present in the old summary, provided that the messages that were exchanged since that summary was produced indictae that those details are becoming less relevant to the continuation of the conversation.
|
|
|
|
<running_summary>
|
|
${previousRunningSummary}
|
|
</running_summary>
|
|
`;
|
|
|
|
const runningSummaryUserPrompt = ({
|
|
messagesSincePreviousRunningSummary,
|
|
mainResponseContent,
|
|
}: {
|
|
messagesSincePreviousRunningSummary: Array<DraftMessage>;
|
|
mainResponseContent: string;
|
|
}) =>
|
|
`${messagesSincePreviousRunningSummary.map(
|
|
(message) =>
|
|
`<${message.role}_message>${message.parts
|
|
.filter((p) => p.type === "text")
|
|
.map((p) => p.text)
|
|
.join("\n")}</${message.role}_message>`
|
|
)}
|
|
<assistant_response>
|
|
${mainResponseContent}
|
|
</assistant_response>
|
|
|
|
Generate a new running summary of the conversation.`;
|
|
|
|
export const messages = router({
|
|
fetchByConversationId: publicProcedure
|
|
.input((x) => x as { conversationId: string })
|
|
.query(async ({ input: { conversationId } }) => {
|
|
const caller = createConversationsCaller({});
|
|
return await caller.fetchMessages({
|
|
conversationId,
|
|
});
|
|
}),
|
|
generateRunningSummary: publicProcedure
|
|
.input(
|
|
(x) =>
|
|
x as {
|
|
previousRunningSummary: string;
|
|
messagesSincePreviousRunningSummary: Array<DraftMessage>;
|
|
mainResponseContent: string;
|
|
}
|
|
)
|
|
.mutation(
|
|
async ({
|
|
input: {
|
|
previousRunningSummary,
|
|
messagesSincePreviousRunningSummary,
|
|
mainResponseContent,
|
|
},
|
|
}) => {
|
|
const runningSummaryResponse = await generateText({
|
|
model: openrouter(MODEL_NAME),
|
|
messages: [
|
|
{
|
|
role: "system" as const,
|
|
content: runningSummarySystemPrompt({
|
|
previousRunningSummary,
|
|
}),
|
|
},
|
|
{
|
|
role: "user" as const,
|
|
content: runningSummaryUserPrompt({
|
|
messagesSincePreviousRunningSummary,
|
|
mainResponseContent,
|
|
}),
|
|
},
|
|
],
|
|
tools: undefined,
|
|
});
|
|
return runningSummaryResponse;
|
|
}
|
|
),
|
|
});
|
|
|
|
export const createCaller = createCallerFactory(messages);
|