From a289db56c79e2283d1dcd30a174c549be6eb3fec Mon Sep 17 00:00:00 2001 From: MT-Fire <798521692@qq.com> Date: Thu, 5 Mar 2026 11:41:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(context):=20=E6=96=B0=E5=A2=9E=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E8=AE=B0=E5=BF=86=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8=E5=AF=B9=E8=AF=9D=E4=B8=AD=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E7=94=A8=E6=88=B7=E8=BE=93=E5=85=A5=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/ChatMain.vue | 22 +++++++++++++++++++++- src/services/api.ts | 30 ++++++++++++++++++------------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/components/chat/ChatMain.vue b/src/components/chat/ChatMain.vue index a8f3a9a..9abc468 100644 --- a/src/components/chat/ChatMain.vue +++ b/src/components/chat/ChatMain.vue @@ -152,6 +152,15 @@ async function handleSend(text: string, attachments: Attachment[], options?: { d chatStore.createConversation(); } + // 从当前会话中提取历史消息(用于上下文记忆),在添加新消息之前提取 + const existingMessages = currentConversation.value?.messages || []; + const MAX_HISTORY_ROUNDS = 20; // 最多保留最近 20 轮(40 条消息) + const historyMessages = existingMessages + .filter((m: any) => m.role === MessageRole.USER || m.role === MessageRole.ASSISTANT) + .filter((m: any) => m.content?.text) // 过滤掉空消息 + .slice(-(MAX_HISTORY_ROUNDS * 2)) + .map((m: any) => ({ role: m.role, content: m.content.text })); + // 添加用户消息 chatStore.addMessage(MessageRole.USER, { type: MessageType.TEXT, @@ -189,9 +198,10 @@ async function handleSend(text: string, attachments: Attachment[], options?: { d message: text, conversationId: currentConversation.value?.id || "", images: imageUrls, - files: fileUrls, // 传递文件 URL,后端会读取内容 + files: fileUrls, model: settings.value.defaultModel, stream: true, + history: historyMessages, deepSearch: options?.deepSearch, webSearch: options?.webSearch, deepThinking: options?.deepThinking, @@ -259,6 +269,15 @@ async function handleRetry(messageId: string) { const userMessage = messages.value[messageIndex - 1]; if (userMessage.role !== MessageRole.USER) return; + // 提取重试位置之前的历史消息(用于上下文记忆) + const MAX_HISTORY_ROUNDS = 20; + const priorMessages = messages.value + .slice(0, messageIndex - 1) // 不包含当前 user 消息和要重试的 assistant 消息 + .filter((m: any) => m.role === MessageRole.USER || m.role === MessageRole.ASSISTANT) + .filter((m: any) => m.content?.text) + .slice(-(MAX_HISTORY_ROUNDS * 2)) + .map((m: any) => ({ role: m.role, content: m.content.text })); + // 重置消息状态 chatStore.updateMessage(messageId, { isError: false, @@ -279,6 +298,7 @@ async function handleRetry(messageId: string) { conversationId: currentConversation.value?.id, model: settings.value.defaultModel, stream: true, + history: priorMessages, }, abortController.value.signal, ); diff --git a/src/services/api.ts b/src/services/api.ts index e15aa29..4f0c16c 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -40,6 +40,8 @@ export interface ChatRequest { maxTokens?: number; systemPrompt?: string; stream?: boolean; + // 历史对话消息(用于上下文记忆) + history?: { role: string; content: string }[]; // 扩展选项 deepSearch?: boolean; webSearch?: boolean; @@ -107,22 +109,26 @@ class ChatApi { } // 将前端简化的请求翻译为 OpenAI 兼容的规范请求体 + // 构建 messages 数组:system + 历史消息 + 当前用户消息 + const systemMessage = { + role: "system", + content: request.systemPrompt || "你是一个智能助手,可以分析用户发送的文字,文件或图片内容,并进行回答。", + }; + const currentUserMessage = { + role: "user", + content: userContent, + }; + const allMessages = request.history && request.history.length > 0 + ? [systemMessage, ...request.history, currentUserMessage] + : [systemMessage, currentUserMessage]; + const openAiRequest = { - model: request.model || "glm-4-flash", // 可能需要指定支持视觉的模型 - messages: [ - { - role: "system", - content: request.systemPrompt || "你是一个智能助手,可以分析用户发送的文字,文件或图片内容,并进行回答。", - }, - { - role: "user", - content: userContent, - }, - ], + model: request.model || "glm-4-flash", + messages: allMessages, stream: true, temperature: request.temperature, max_tokens: request.maxTokens, - files: request.files || [], // 传递文件 URL 列表给后端 + files: request.files || [], // 扩展参数传递给我们的 Python 后端进行特殊处理 deepSearch: request.deepSearch, webSearch: request.webSearch,