mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 15:58:38 +01:00
fix chat streaming + add "deleted" field to chats
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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 => {
|
||||||
@@ -7,10 +7,10 @@ export default defineEventHandler(async event => {
|
|||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
const { project_id } = data;
|
const { project_id } = data;
|
||||||
|
|
||||||
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;
|
||||||
});
|
});
|
||||||
@@ -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());
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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: [] };
|
||||||
|
|||||||
@@ -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() },
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user