From d21957a8f96aa8c14ec27ce148a06560d9373d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B3=E5=85=83=E7=9A=93?= Date: Fri, 23 May 2025 22:51:19 +0800 Subject: [PATCH] Made a basic AI chat streaming content, but there is still no auth yet, should be added soon. And add the test file test.vue to be ignored. This file is just a poc (it is AI generated based on my API file) --- .gitignore | 3 ++ server/api/ai/chat/[slug].ts | 83 +++++++++++++++++++++++++----------- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index dc591ea..05851ba 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ __pycache__ *.sql !database/*.sql _dt_*.py + +# Testing files +test.vue diff --git a/server/api/ai/chat/[slug].ts b/server/api/ai/chat/[slug].ts index fa562fb..4b18b38 100644 --- a/server/api/ai/chat/[slug].ts +++ b/server/api/ai/chat/[slug].ts @@ -4,30 +4,39 @@ import sql from "~/server/components/postgres"; const groq = new Groq(); export default defineEventHandler(async (event) => { + const host = await getRequestHost(event); + const protocol = await getRequestProtocol(event); + const hears = await getRequestHeaders(event); const slug = getRouterParam(event, "slug"); + const body = await readBody(event); if (!slug) { throw createError({ statusCode: 400, message: "A UUID is required for this action.", }); } + const getChatHistory = await sql` - select * from chatHistory + select * from chat_history where uuid = ${slug} - order by created_ata asc - `; - if (getChatHistory.length === 0) { - } - const body = await readBody(event); - const fetchNewsArticle = await sql` - select * from newArticle - where newsid = ${body.newsid} - `; + order by created_at asc + `; + + const buildURL = protocol + "://" + host + "/api/news/get/lt/" + "LX30VwG"; + const data = await fetch(buildURL); + const fetchNewsArticle = await data.json(); + + // Set headers for Server-Sent Events + setHeader(event, "Content-Type", "text/plain; charset=utf-8"); + setHeader(event, "Cache-Control", "no-cache"); + setHeader(event, "Connection", "keep-alive"); + setHeader(event, "Access-Control-Allow-Origin", "*"); + const chatCompletion = await groq.chat.completions.create({ messages: [ { role: "system", - content: `You are a news chat, the following content will be used to chat with the user title: ${fetchNewsArticle.title}\n content: ${fetchNewsArticle.content}`, + content: `You are a news chat, the following content will be used to chat with the user title: ${fetchNewsArticle.title} article: ${fetchNewsArticle.paragraph} origin: ${fetchNewsArticle.origin} author: ${fetchNewsArticle.author}`, }, ...getChatHistory.map((chat) => ({ role: chat.role, @@ -35,7 +44,7 @@ export default defineEventHandler(async (event) => { })), { role: "user", - content: `${body}`, + content: body.message, }, ], model: "llama-3.1-8b-instant", @@ -45,20 +54,44 @@ export default defineEventHandler(async (event) => { stream: true, stop: null, }); + + /* + // Save user message await sql` INSERT INTO chat_history (uuid, role, content) - VALUES (${slug}, 'user', ${body}) - `; + VALUES (${slug}, 'user', ${body.message}) + `; */ + let assistantResponse = ""; - for await (const chunk of chatCompletion) { - const content = chunk.choices[0]?.delta?.content || ""; - assistantResponse += content; - process.stdout.write(content); - } - if (assistantResponse) { - await sql` - INSERT INTO chat_history (uuid, role, content) - VALUES (${slug}, 'assistant', ${assistantResponse}) - `; - } + + // Create a readable stream + const stream = new ReadableStream({ + async start(controller) { + try { + for await (const chunk of chatCompletion) { + const content = chunk.choices[0]?.delta?.content || ""; + if (content) { + assistantResponse += content; + // Send chunk to client + controller.enqueue(new TextEncoder().encode(content)); + } + } + + /* + // Save complete assistant response + if (assistantResponse) { + await sql` + INSERT INTO chat_history (uuid, role, content) + VALUES (${slug}, 'assistant', ${assistantResponse}) + `; + } */ + + controller.close(); + } catch (error) { + controller.error(error); + } + }, + }); + + return sendStream(event, stream); });