generate and save facts
This commit is contained in:
@@ -2,6 +2,7 @@ import {
|
||||
Box,
|
||||
Group,
|
||||
JsonInput,
|
||||
List,
|
||||
Stack,
|
||||
Tabs,
|
||||
Textarea,
|
||||
@@ -30,6 +31,7 @@ export default function ChatPage() {
|
||||
const message = useStore((state) => state.message);
|
||||
const systemPrompt = useStore((state) => state.systemPrompt);
|
||||
const parameters = useStore((state) => state.parameters);
|
||||
const facts = useStore((state) => state.facts);
|
||||
const loading = useStore((state) => state.loading);
|
||||
const setConversationId = useStore((state) => state.setConversationId);
|
||||
const setConversationTitle = useStore((state) => state.setConversationTitle);
|
||||
@@ -37,9 +39,14 @@ export default function ChatPage() {
|
||||
const setMessage = useStore((state) => state.setMessage);
|
||||
const setSystemPrompt = useStore((state) => state.setSystemPrompt);
|
||||
const setParameters = useStore((state) => state.setParameters);
|
||||
const setFacts = useStore((state) => state.setFacts);
|
||||
const setLoading = useStore((state) => state.setLoading);
|
||||
|
||||
const { conversation, messages: initialMessages } = useData<Data>();
|
||||
const {
|
||||
conversation,
|
||||
messages: initialMessages,
|
||||
facts: initialFacts,
|
||||
} = useData<Data>();
|
||||
|
||||
useEffect(() => {
|
||||
setConversationId(conversationId);
|
||||
@@ -61,6 +68,10 @@ export default function ChatPage() {
|
||||
setMessages(initialMessages);
|
||||
}, [initialMessages, setMessages]);
|
||||
|
||||
useEffect(() => {
|
||||
setFacts(initialFacts);
|
||||
}, [initialFacts, setFacts]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
@@ -84,6 +95,7 @@ export default function ChatPage() {
|
||||
<Tabs.Tab value="message">Message</Tabs.Tab>
|
||||
<Tabs.Tab value="system-prompt">System Prompt</Tabs.Tab>
|
||||
<Tabs.Tab value="parameters">Parameters</Tabs.Tab>
|
||||
<Tabs.Tab value="facts">Facts</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Tabs.Panel value="message">
|
||||
<Messages messages={messages} />
|
||||
@@ -131,6 +143,7 @@ export default function ChatPage() {
|
||||
];
|
||||
setMessages(messagesWithAssistantMessage);
|
||||
setMessage("");
|
||||
setFacts(response.insertedFacts);
|
||||
setLoading(false);
|
||||
}
|
||||
}}
|
||||
@@ -153,6 +166,13 @@ export default function ChatPage() {
|
||||
onChange={(value) => setParameters(JSON.parse(value))}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="facts">
|
||||
<List>
|
||||
{facts.map((fact) => (
|
||||
<List.Item key={fact.id}>{fact.content}</List.Item>
|
||||
))}
|
||||
</List>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
</>
|
||||
);
|
||||
@@ -164,7 +184,6 @@ function Messages({
|
||||
messages: Array<DraftMessage | CommittedMessage>;
|
||||
}) {
|
||||
const theme = useMantineTheme();
|
||||
console.log("messages", messages);
|
||||
return (
|
||||
<Stack gap="md" justify="flex-start">
|
||||
{messages.map((message, index) => (
|
||||
@@ -188,7 +207,7 @@ function Messages({
|
||||
</div>
|
||||
<Markdown>{message.content}</Markdown>
|
||||
</Box>
|
||||
{"runningSummary" in message && (
|
||||
{"runningSummary" in message && message.runningSummary && (
|
||||
<Box w="75%" bd="dotted" p="md" bdrs="md">
|
||||
<div>
|
||||
<strong>Running Summary:</strong>
|
||||
|
||||
@@ -12,5 +12,5 @@ export const data = async (pageContext: PageContextServer) => {
|
||||
const messages = await caller.fetchMessages({
|
||||
conversationId: id,
|
||||
});
|
||||
return { conversation, messages };
|
||||
return { conversation, messages, facts: [] };
|
||||
};
|
||||
|
||||
+67
-9
@@ -4,7 +4,7 @@ import {
|
||||
createCallerFactory,
|
||||
} from "../../trpc/server";
|
||||
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
||||
import { generateText } from "ai";
|
||||
import { generateObject, generateText, jsonSchema } from "ai";
|
||||
import type { Message as UIMessage } from "ai";
|
||||
import type {
|
||||
OtherParameters,
|
||||
@@ -17,7 +17,7 @@ import { env } from "../../server/env.js";
|
||||
// ConsistencyLevelEnum,
|
||||
// type NumberArrayId,
|
||||
// } from "@zilliz/milvus2-sdk-node";
|
||||
import { db } from "../../database/lowdb";
|
||||
import { db, type Fact } from "../../database/lowdb";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
const mainSystemPrompt = ({
|
||||
@@ -30,6 +30,15 @@ This is a summary of the conversation so far, from your point-of-view (so "I" an
|
||||
${previousRunningSummary}
|
||||
</running_summary>
|
||||
`;
|
||||
const factsFromUserMessageSystemPrompt = ({
|
||||
previousRunningSummary,
|
||||
}: {
|
||||
previousRunningSummary: string;
|
||||
}) => `Given the following summary of a conversation, coupled with the messages exchanged since that summary was produced, extract new facts that can be gleaned from the conversation.
|
||||
<running_summary>
|
||||
${previousRunningSummary}
|
||||
</running_summary>
|
||||
`;
|
||||
const runningSummarySystemPrompt = ({
|
||||
previousRunningSummary,
|
||||
}: {
|
||||
@@ -69,10 +78,19 @@ export const chat = router({
|
||||
deleteConversation: publicProcedure
|
||||
.input((x) => x as { id: string })
|
||||
.mutation(async ({ input: { id } }) => {
|
||||
await db.data.conversations.splice(
|
||||
db.data.conversations.splice(
|
||||
db.data.conversations.findIndex((c) => c.id === id),
|
||||
1,
|
||||
);
|
||||
const deletedMessageIds = db.data.messages
|
||||
.filter((m) => m.conversationId === id)
|
||||
.map((m) => m.id);
|
||||
db.data.messages = db.data.messages.filter(
|
||||
(m) => m.conversationId !== id,
|
||||
);
|
||||
db.data.facts = db.data.facts.filter(
|
||||
(fact) => !deletedMessageIds.includes(fact.sourceMessageId),
|
||||
);
|
||||
db.write();
|
||||
return { ok: true };
|
||||
}),
|
||||
@@ -136,7 +154,7 @@ export const chat = router({
|
||||
index: messages.length - 1,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
await db.data.messages.push(insertedUserMessage);
|
||||
db.data.messages.push(insertedUserMessage);
|
||||
// do not db.write() until the end
|
||||
|
||||
/** Generate a new message from the model, but hold-off on adding it to
|
||||
@@ -172,6 +190,43 @@ export const chat = router({
|
||||
* injection, because we're sending the user's message unadulterated to
|
||||
* the model; there's no reason to inject the same Facts that the model is
|
||||
* already using to generate its response.) */
|
||||
const factsFromUserMessageResponse = await generateObject<{
|
||||
facts: Array<string>;
|
||||
}>({
|
||||
model: openrouter("mistralai/mistral-nemo"),
|
||||
messages: [
|
||||
{
|
||||
role: "system" as const,
|
||||
content: factsFromUserMessageSystemPrompt({
|
||||
previousRunningSummary,
|
||||
}),
|
||||
},
|
||||
...messages.slice(previousRunningSummaryIndex + 1),
|
||||
],
|
||||
schema: jsonSchema({
|
||||
type: "object",
|
||||
properties: {
|
||||
facts: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
maxSteps: 3,
|
||||
tools: undefined,
|
||||
...parameters,
|
||||
});
|
||||
const insertedFacts: Array<Fact> =
|
||||
factsFromUserMessageResponse.object.facts.map((fact) => ({
|
||||
id: nanoid(),
|
||||
userId: "1",
|
||||
sourceMessageId: insertedUserMessage.id,
|
||||
content: fact,
|
||||
createdAt: new Date().toISOString(),
|
||||
}));
|
||||
db.data.facts.push(...insertedFacts);
|
||||
/** Extract Facts from the model's response, and add them to the database,
|
||||
* linking the Facts with the messages they came from. */
|
||||
/** For each Fact produced in the two fact-extraction steps, generate
|
||||
@@ -246,12 +301,15 @@ export const chat = router({
|
||||
index: messages.length,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
await db.data.messages.push(insertedAssistantMessage);
|
||||
db.data.messages.push(insertedAssistantMessage);
|
||||
|
||||
await db.write();
|
||||
/** TODO: notify the caller, somehow, that some messages were saved to
|
||||
* the database and/or were outfitted with runningSummaries, so the
|
||||
* caller can update its UI state. */
|
||||
return { insertedAssistantMessage, insertedUserMessage };
|
||||
|
||||
return {
|
||||
insertedAssistantMessage,
|
||||
insertedUserMessage,
|
||||
insertedFacts,
|
||||
};
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user