|
|
@ -17,9 +17,8 @@ import { env } from "../../server/env.js";
|
|
|
|
// ConsistencyLevelEnum,
|
|
|
|
// ConsistencyLevelEnum,
|
|
|
|
// type NumberArrayId,
|
|
|
|
// type NumberArrayId,
|
|
|
|
// } from "@zilliz/milvus2-sdk-node";
|
|
|
|
// } from "@zilliz/milvus2-sdk-node";
|
|
|
|
import { db } from "../../database/postgres";
|
|
|
|
import { db } from "../../database/lowdb";
|
|
|
|
import type { ConversationsId } from "../../database/generated/public/Conversations";
|
|
|
|
import { nanoid } from "nanoid";
|
|
|
|
import type { UsersId } from "../../database/generated/public/Users";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const mainSystemPrompt = ({
|
|
|
|
const mainSystemPrompt = ({
|
|
|
|
systemPrompt,
|
|
|
|
systemPrompt,
|
|
|
@ -47,75 +46,64 @@ const openrouter = createOpenRouter({
|
|
|
|
|
|
|
|
|
|
|
|
export const chat = router({
|
|
|
|
export const chat = router({
|
|
|
|
listConversations: publicProcedure.query(async () => {
|
|
|
|
listConversations: publicProcedure.query(async () => {
|
|
|
|
const rows = await db.selectFrom("conversations").selectAll().execute();
|
|
|
|
const rows = await db.data.conversations;
|
|
|
|
return rows;
|
|
|
|
return rows;
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
fetchConversation: publicProcedure
|
|
|
|
fetchConversation: publicProcedure
|
|
|
|
.input((x) => x as { id: number })
|
|
|
|
.input((x) => x as { id: string })
|
|
|
|
.query(async ({ input: { id } }) => {
|
|
|
|
.query(async ({ input: { id } }) => {
|
|
|
|
const row = await db
|
|
|
|
const row = await db.data.conversations.find((c) => c.id === id);
|
|
|
|
.selectFrom("conversations")
|
|
|
|
|
|
|
|
.selectAll()
|
|
|
|
|
|
|
|
.where("id", "=", id as ConversationsId)
|
|
|
|
|
|
|
|
.executeTakeFirst();
|
|
|
|
|
|
|
|
return row;
|
|
|
|
return row;
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
createConversation: publicProcedure.mutation(async () => {
|
|
|
|
createConversation: publicProcedure.mutation(async () => {
|
|
|
|
const title = "New Conversation";
|
|
|
|
const title = "New Conversation";
|
|
|
|
const row = await db
|
|
|
|
const row = {
|
|
|
|
.insertInto("conversations")
|
|
|
|
id: nanoid(),
|
|
|
|
.values({
|
|
|
|
|
|
|
|
title,
|
|
|
|
title,
|
|
|
|
user_id: 1 as UsersId,
|
|
|
|
userId: "1",
|
|
|
|
})
|
|
|
|
};
|
|
|
|
.returningAll()
|
|
|
|
await db.data.conversations.push(row);
|
|
|
|
.executeTakeFirst();
|
|
|
|
db.write();
|
|
|
|
return row;
|
|
|
|
return row;
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
deleteConversation: publicProcedure
|
|
|
|
deleteConversation: publicProcedure
|
|
|
|
.input((x) => x as { id: number })
|
|
|
|
.input((x) => x as { id: string })
|
|
|
|
.mutation(async ({ input: { id } }) => {
|
|
|
|
.mutation(async ({ input: { id } }) => {
|
|
|
|
const result = await db
|
|
|
|
await db.data.conversations.splice(
|
|
|
|
.deleteFrom("conversations")
|
|
|
|
db.data.conversations.findIndex((c) => c.id === id),
|
|
|
|
.where("id", "=", Number(id) as ConversationsId)
|
|
|
|
1,
|
|
|
|
.execute();
|
|
|
|
);
|
|
|
|
return result;
|
|
|
|
db.write();
|
|
|
|
|
|
|
|
return { ok: true };
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
updateConversationTitle: publicProcedure
|
|
|
|
updateConversationTitle: publicProcedure
|
|
|
|
.input(
|
|
|
|
.input(
|
|
|
|
(x) =>
|
|
|
|
(x) =>
|
|
|
|
x as {
|
|
|
|
x as {
|
|
|
|
id: number;
|
|
|
|
id: string;
|
|
|
|
title: string;
|
|
|
|
title: string;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.mutation(async ({ input: { id, title } }) => {
|
|
|
|
.mutation(async ({ input: { id, title } }) => {
|
|
|
|
const result = await db
|
|
|
|
const conversation = await db.data.conversations.find((c) => c.id === id);
|
|
|
|
.updateTable("conversations")
|
|
|
|
if (!conversation) throw new Error("Conversation not found");
|
|
|
|
.set({ title })
|
|
|
|
conversation.title = title;
|
|
|
|
.where("id", "=", Number(id) as ConversationsId)
|
|
|
|
db.write();
|
|
|
|
.execute();
|
|
|
|
return { ok: true };
|
|
|
|
return result[0];
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
fetchMessages: publicProcedure
|
|
|
|
fetchMessages: publicProcedure
|
|
|
|
.input((x) => x as { conversationId: number })
|
|
|
|
.input((x) => x as { conversationId: string })
|
|
|
|
.query(async ({ input: { conversationId } }) => {
|
|
|
|
.query(async ({ input: { conversationId } }) => {
|
|
|
|
const rows = await db
|
|
|
|
const rows = await db.data.messages.filter(
|
|
|
|
.selectFrom("messages")
|
|
|
|
(m) => m.conversationId === conversationId,
|
|
|
|
.selectAll()
|
|
|
|
);
|
|
|
|
.where("conversation_id", "=", conversationId as ConversationsId)
|
|
|
|
return rows as Array<CommittedMessage>;
|
|
|
|
.execute();
|
|
|
|
|
|
|
|
return rows.map((row) => ({
|
|
|
|
|
|
|
|
...row,
|
|
|
|
|
|
|
|
conversationId: conversationId as ConversationsId,
|
|
|
|
|
|
|
|
runningSummary: row.running_summary,
|
|
|
|
|
|
|
|
})) as Array<CommittedMessage>;
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
sendMessage: publicProcedure
|
|
|
|
sendMessage: publicProcedure
|
|
|
|
.input(
|
|
|
|
.input(
|
|
|
|
(x) =>
|
|
|
|
(x) =>
|
|
|
|
x as {
|
|
|
|
x as {
|
|
|
|
conversationId: number;
|
|
|
|
conversationId: string;
|
|
|
|
messages: Array<DraftMessage | CommittedMessage>;
|
|
|
|
messages: Array<DraftMessage | CommittedMessage>;
|
|
|
|
systemPrompt: string;
|
|
|
|
systemPrompt: string;
|
|
|
|
parameters: OtherParameters;
|
|
|
|
parameters: OtherParameters;
|
|
|
@ -140,17 +128,17 @@ export const chat = router({
|
|
|
|
.runningSummary as string)
|
|
|
|
.runningSummary as string)
|
|
|
|
: "";
|
|
|
|
: "";
|
|
|
|
/** Save the incoming message to the database. */
|
|
|
|
/** Save the incoming message to the database. */
|
|
|
|
const insertedUserMessage = await db
|
|
|
|
const insertedUserMessage: CommittedMessage = {
|
|
|
|
.insertInto("messages")
|
|
|
|
id: nanoid(),
|
|
|
|
.values({
|
|
|
|
conversationId,
|
|
|
|
conversation_id: conversationId as ConversationsId,
|
|
|
|
|
|
|
|
content: messages[messages.length - 1].content,
|
|
|
|
content: messages[messages.length - 1].content,
|
|
|
|
role: "user" as const,
|
|
|
|
role: "user" as const,
|
|
|
|
index: messages.length - 1,
|
|
|
|
index: messages.length - 1,
|
|
|
|
created_at: new Date().toISOString(),
|
|
|
|
createdAt: new Date().toISOString(),
|
|
|
|
})
|
|
|
|
};
|
|
|
|
.returning(["id", "index"])
|
|
|
|
await db.data.messages.push(insertedUserMessage);
|
|
|
|
.executeTakeFirst();
|
|
|
|
// do not db.write() until the end
|
|
|
|
|
|
|
|
|
|
|
|
/** Generate a new message from the model, but hold-off on adding it to
|
|
|
|
/** Generate a new message from the model, but hold-off on adding it to
|
|
|
|
* the database until we produce the associated running-summary, below.
|
|
|
|
* the database until we produce the associated running-summary, below.
|
|
|
|
* The model should be given the conversation summary thus far, and of
|
|
|
|
* The model should be given the conversation summary thus far, and of
|
|
|
@ -249,18 +237,17 @@ export const chat = router({
|
|
|
|
tools: undefined,
|
|
|
|
tools: undefined,
|
|
|
|
...parameters,
|
|
|
|
...parameters,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const insertedAssistantMessage = await db
|
|
|
|
const insertedAssistantMessage: CommittedMessage = {
|
|
|
|
.insertInto("messages")
|
|
|
|
id: nanoid(),
|
|
|
|
.values({
|
|
|
|
conversationId,
|
|
|
|
conversation_id: conversationId as ConversationsId,
|
|
|
|
|
|
|
|
content: mainResponse.text,
|
|
|
|
content: mainResponse.text,
|
|
|
|
running_summary: runningSummaryResponse.text,
|
|
|
|
runningSummary: runningSummaryResponse.text,
|
|
|
|
role: "assistant" as const,
|
|
|
|
role: "assistant" as const,
|
|
|
|
index: messages.length,
|
|
|
|
index: messages.length,
|
|
|
|
created_at: new Date().toISOString(),
|
|
|
|
createdAt: new Date().toISOString(),
|
|
|
|
})
|
|
|
|
};
|
|
|
|
.returningAll()
|
|
|
|
await db.data.messages.push(insertedAssistantMessage);
|
|
|
|
.executeTakeFirst();
|
|
|
|
await db.write();
|
|
|
|
/** TODO: notify the caller, somehow, that some messages were saved to
|
|
|
|
/** TODO: notify the caller, somehow, that some messages were saved to
|
|
|
|
* the database and/or were outfitted with runningSummaries, so the
|
|
|
|
* the database and/or were outfitted with runningSummaries, so the
|
|
|
|
* caller can update its UI state. */
|
|
|
|
* caller can update its UI state. */
|
|
|
|