fix chat streaming + add "deleted" field to chats

This commit is contained in:
Emily
2024-12-13 15:07:34 +01:00
parent f358bb9bb6
commit 6307e09dc3
7 changed files with 36 additions and 26 deletions

View File

@@ -26,7 +26,7 @@ export function useComputedHeaders(customOptions?: CustomOptions) {
const useTimeOffset = customOptions?.useTimeOffset || true; const useTimeOffset = customOptions?.useTimeOffset || true;
const headers = computed<Record<string, string>>(() => { const headers = computed<Record<string, string>>(() => {
console.trace('Computed recalculated'); // console.trace('Computed recalculated');
const parsedCustom: Record<string, string> = {} const parsedCustom: Record<string, string> = {}
const customKeys = Object.keys(customOptions?.custom || {}); const customKeys = Object.keys(customOptions?.custom || {});
for (const key of customKeys) { for (const key of customKeys) {

View File

@@ -24,8 +24,14 @@ const currentChatId = ref<string>("");
const currentChatMessages = ref<{ role: string, content: string, charts?: any[] }[]>([]); const currentChatMessages = ref<{ role: string, content: string, charts?: any[] }[]>([]);
const currentChatMessageDelta = ref<string>(''); const currentChatMessageDelta = ref<string>('');
const scroller = ref<HTMLDivElement | null>(null); const currentChatMessageDeltaHtml = computed(() => {
const lastData = currentChatMessageDelta.value.match(/\[(data:(.*?))\]/g);
const cleanMessage = currentChatMessageDelta.value.replace(/\[(data:(.*?))\]/g, '');
if (!lastData || lastData.length == 0) return cleanMessage;
return `<div> <span>LOADER HERE: ${lastData.at(-1)}</span> ${cleanMessage} </div>`;
});
const scroller = ref<HTMLDivElement | null>(null);
async function pollSendMessageStatus(chat_id: string, times: number, updateStatus: (status: string) => any) { async function pollSendMessageStatus(chat_id: string, times: number, updateStatus: (status: string) => any) {
@@ -46,7 +52,7 @@ async function pollSendMessageStatus(chat_id: string, times: number, updateStatu
} else { } else {
currentChatMessages.value.push({ currentChatMessages.value.push({
role: 'assistant', role: 'assistant',
content: currentChatMessageDelta.value.replace(/\[data:.*?\]/g,''), content: currentChatMessageDelta.value.replace(/\[data:.*?\]/g, ''),
}); });
currentChatMessageDelta.value = ''; currentChatMessageDelta.value = '';
@@ -75,8 +81,6 @@ async function sendMessage() {
const res = await $fetch<{ chat_id: string }>(`/api/ai/send_message`, { method: 'POST', body: JSON.stringify(body), headers: useComputedHeaders({ useSnapshotDates: false, custom: { 'Content-Type': 'application/json' } }).value }); const res = await $fetch<{ chat_id: string }>(`/api/ai/send_message`, { method: 'POST', body: JSON.stringify(body), headers: useComputedHeaders({ useSnapshotDates: false, custom: { 'Content-Type': 'application/json' } }).value });
currentChatId.value = res.chat_id; currentChatId.value = res.chat_id;
currentChatMessages.value.push({ role: 'assistant', content: '', charts: [] });
await reloadChatsRemaining(); await reloadChatsRemaining();
await reloadChatsList(); await reloadChatsList();
@@ -237,16 +241,16 @@ const { visible: pricingDrawerVisible } = usePricingDrawer()
</div> </div>
<div class="flex items-center gap-3 justify-start w-full poppins text-[1.1rem]" <div class="flex items-center gap-3 justify-start w-full poppins text-[1.1rem]"
v-if="currentChatMessageDelta"> v-if="currentChatMessageDelta">
<div class="flex items-center justify-center shrink-0"> <div class="flex items-center justify-center shrink-0">
<img class="h-[3.5rem] w-auto" :src="'analyst.png'"> <img class="h-[3.5rem] w-auto" :src="'analyst.png'">
</div> </div>
<div class="max-w-[70%] text-text/90 ai-message whitespace-pre-wrap"> <div class="max-w-[70%] text-text/90 ai-message whitespace-pre-wrap">
{{ currentChatMessageDelta.replace(/\[(data:(.*?))\]/g, 'Processing: $2\n') }} <vue-markdown :source="currentChatMessageDeltaHtml" :options="{
html: true,
breaks: true,
}" />
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
import { AiChatModel } from "@schema/ai/AiChatSchema"; import { AiChatModel } from "@schema/ai/AiChatSchema";
export default defineEventHandler(async event => { export default defineEventHandler(async event => {
@@ -11,6 +11,6 @@ export default defineEventHandler(async event => {
if (!event.context.params) return; if (!event.context.params) return;
const chat_id = event.context.params['chat_id']; const chat_id = event.context.params['chat_id'];
const result = await AiChatModel.deleteOne({ _id: chat_id, project_id }); const result = await AiChatModel.updateOne({ _id: chat_id, project_id }, { deleted: true });
return result.deletedCount > 0; return result.modifiedCount > 0;
}); });

View File

@@ -9,7 +9,7 @@ export default defineEventHandler(async event => {
const { project_id } = data; const { project_id } = data;
const chatList = await AiChatModel.find({ project_id }, { _id: 1, title: 1 }, { sort: { updated_at: 1 } }); const chatList = await AiChatModel.find({ project_id, deleted: false }, { _id: 1, title: 1 }, { sort: { updated_at: 1 } });
return chatList.map(e => e.toJSON()); return chatList.map(e => e.toJSON());

View File

@@ -47,8 +47,8 @@ export default defineEventHandler(async event => {
await updateChatStatus(targetChatId, currentStatus.join(''), false); await updateChatStatus(targetChatId, currentStatus.join(''), false);
}, },
onFinish: async calls => { onFinish: async calls => {
currentStatus.push('[data:FunctionFinish]'); // currentStatus.push('[data:FunctionFinish]');
await updateChatStatus(targetChatId, currentStatus.join(''), false); // await updateChatStatus(targetChatId, currentStatus.join(''), false);
} }
}); });

View File

@@ -128,6 +128,15 @@ async function elaborateResponse(messages: OpenAI.Chat.Completions.ChatCompletio
functionCall.result = functionResult; functionCall.result = functionResult;
await callbacks?.onFunctionResult?.(functionCall.name, functionResult); await callbacks?.onFunctionResult?.(functionCall.name, functionResult);
addMessageToChat({
tool_call_id: functionCall.tool_call_id,
role: 'tool',
content: JSON.stringify(functionResult)
}, chat_id);
addMessageToChat({ addMessageToChat({
role: 'assistant', role: 'assistant',
content: delta.content, content: delta.content,
@@ -141,14 +150,7 @@ async function elaborateResponse(messages: OpenAI.Chat.Completions.ChatCompletio
arguments: functionCall.argsRaw.join('') arguments: functionCall.argsRaw.join('')
} }
} }
], ]
parsed: null
}, chat_id);
addMessageToChat({
tool_call_id: functionCall.tool_call_id,
role: 'tool',
content: JSON.stringify(functionResult)
}, chat_id); }, chat_id);
@@ -181,6 +183,7 @@ export async function sendMessageOnChat(text: string, pid: string, initial_chat_
if (chatMessages && chatMessages.length > 0) { if (chatMessages && chatMessages.length > 0) {
messages.push(...chatMessages); messages.push(...chatMessages);
await updateChatStatus(chat_id, '', false);
} else { } else {
const roleMessage: OpenAI.Chat.Completions.ChatCompletionMessageParam = { const roleMessage: OpenAI.Chat.Completions.ChatCompletionMessageParam = {
role: 'system', role: 'system',
@@ -198,8 +201,9 @@ export async function sendMessageOnChat(text: string, pid: string, initial_chat_
try { try {
const streamResponse = await elaborateResponse(messages, pid, chat_id, callbacks); const streamResponse = await elaborateResponse(messages, pid, chat_id, callbacks);
await addMessageToChat({ role: 'assistant', refusal: null, content: await streamResponse.finalContent() }, chat_id); const finalContent = await streamResponse.finalContent();
return { content: '', charts: [] }; await addMessageToChat({ role: 'assistant', refusal: null, content: finalContent }, chat_id);
return { content: finalContent, charts: [] };
} catch (ex: any) { } catch (ex: any) {
console.error(ex); console.error(ex);
return { content: ex.message, charts: [] }; return { content: ex.message, charts: [] };

View File

@@ -7,6 +7,7 @@ export type TAiChatSchema = {
status: string, status: string,
completed: boolean, completed: boolean,
title: string, title: string,
deleted: boolean,
created_at: Date, created_at: Date,
updated_at: Date updated_at: Date
} }
@@ -17,6 +18,7 @@ const AiChatSchema = new Schema<TAiChatSchema>({
completed: { type: Boolean }, completed: { type: Boolean },
messages: [{ _id: false, type: Schema.Types.Mixed }], messages: [{ _id: false, type: Schema.Types.Mixed }],
title: { type: String, required: true }, title: { type: String, required: true },
deleted: { type: Boolean, default: false },
created_at: { type: Date, default: () => Date.now() }, created_at: { type: Date, default: () => Date.now() },
updated_at: { type: Date, default: () => Date.now() }, updated_at: { type: Date, default: () => Date.now() },
}); });