diff --git a/src/routers/chat_router.py b/src/routers/chat_router.py index f7a9271c..9f50d2da 100644 --- a/src/routers/chat_router.py +++ b/src/routers/chat_router.py @@ -28,14 +28,30 @@ def chat_post( cur_res_id: str = Body(...)): history_manager = HistoryManager(history) - new_query, refs = startup.retriever(query, history_manager.messages, meta) - refs_pool[cur_res_id] = refs - messages = history_manager.get_history_with_msg(new_query, max_rounds=meta.get('history_round')) - history_manager.add_user(query) - logger.debug(f"Web history: {history_manager.messages}") + def make_chunk(content, status, history): + return json.dumps({ + "response": content, + "history": history, + "model_name": startup.config.model_name, + "status": status, + }, ensure_ascii=False).encode('utf-8') + b"\n" def generate_response(): + + if meta.get("enable_retrieval"): + chunk = make_chunk("", "searching", history=None) + yield chunk + + new_query, refs = startup.retriever(query, history_manager.messages, meta) + refs_pool[cur_res_id] = refs + else: + new_query = query + + messages = history_manager.get_history_with_msg(new_query, max_rounds=meta.get('history_round')) + history_manager.add_user(query) + logger.debug(f"Web history: {history_manager.messages}") + content = "" for delta in startup.model.predict(messages, stream=True): if not delta.content: @@ -47,12 +63,8 @@ def chat_post( content += delta.content logger.debug(f"Response: {content}") - - _chunk = json.dumps({ - "response": content, - "history": history_manager.update_ai(content), - }, ensure_ascii=False).encode('utf-8') + b"\n" - yield _chunk + chunk = make_chunk(content, "loading", history=history_manager.update_ai(content)) + yield chunk return StreamingResponse(generate_response(), media_type='application/json') diff --git a/web/src/components/ChatComponent.vue b/web/src/components/ChatComponent.vue index 40d84b8c..80dcf95c 100644 --- a/web/src/components/ChatComponent.vue +++ b/web/src/components/ChatComponent.vue @@ -16,10 +16,10 @@
-
-
+
+ 流式输出
+
+
+ 总结对话标题
+
+
+ 启用检索
+
+
+ 最大历史轮数 +
+ +
知识库
@@ -62,24 +75,15 @@
-
+
图数据库
-
+
搜索引擎(Bing)
-
- 流式输出
-
-
- 总结对话标题
-
-
+
重写查询
-
- 最大历史轮数 -
@@ -104,12 +108,19 @@ :class="message.role" >

{{ message.text }}

-
+
-
请求错误,请重试
+
正在检索……
+
+ 请求错误,请重试 +
{ role: 'received', text: message, refs, - status: "querying", + status: "init", }) scrollToBottom() } -const updateMessage = (text, id, refs, status) => { - const message = conv.value.messages.find((message) => message.id === id); +const updateMessage = (info) => { + const message = conv.value.messages.find((message) => message.id === info.id); if (message) { // 只有在 text 不为空时更新 - if (text !== null && text !== undefined && text !== '') { - message.text = text; + if (info.text !== null && info.text !== undefined && info.text !== '') { + message.text = info.text; } // 只有在 refs 不为空时更新 - if (refs !== null && refs !== undefined) { - message.refs = refs; + if (info.refs !== null && info.refs !== undefined) { + message.refs = info.refs; + } - // 如果 refs 里面的 model_name 不为空时更新 - if (refs.model_name !== null && refs.model_name !== undefined && refs.model_name !== '') { - message.model_name = refs.model_name; - } + if (info.model_name !== null && info.model_name !== undefined && info.model_name !== '') { + message.model_name = info.model_name; } // 只有在 status 不为空时更新 - if (status !== null && status !== undefined && status !== '') { - message.status = status; + if (info.status !== null && info.status !== undefined && info.status !== '') { + message.status = info.status; } } else { console.error('Message not found'); @@ -412,11 +423,21 @@ const fetchChatResponse = (user_input, cur_res_id) => { const readChunk = () => { return reader.read().then(({ done, value }) => { if (done) { - fetchRefs(cur_res_id).then((data) => { - console.log(data) - updateMessage(null, cur_res_id, data, "finished"); + const message = conv.value.messages.find((message) => message.id === cur_res_id) + if (message.refs && message.refs.meta.enable_retrieval) { + console.log("fetching refs") + fetchRefs(cur_res_id).then((data) => { + console.log(data) + updateMessage({ + id: cur_res_id, + refs: data, + status: "finished", + }); + updateStatus(cur_res_id, "finished"); + }) + } else { updateStatus(cur_res_id, "finished"); - }) + } isStreaming.value = false; if (conv.value.messages.length === 2) { renameTitle(); } return; @@ -426,9 +447,16 @@ const fetchChatResponse = (user_input, cur_res_id) => { buffer += chunk; try { const data = JSON.parse(chunk); - updateMessage(data.response, cur_res_id, data.refs, "loading"); + updateMessage({ + id: cur_res_id, + text: data.response, + model_name: data.model_name, + status: data.status, + }); console.debug(data.response) - conv.value.history = data.history; + if (data.history) { + conv.value.history = data.history; + } } catch (e) { // console.debug('JSON 解析错误:', e, chunk); } @@ -444,9 +472,6 @@ const fetchChatResponse = (user_input, cur_res_id) => { updateStatus(cur_res_id, "error"); isStreaming.value = false; }) - .finally(() => { - isStreaming.value = false; - }); } const fetchRefs = (cur_res_id) => { @@ -484,6 +509,19 @@ const sendMessage = () => { } } +const retryMessage = (id) => { + // 找到 id 对应的 message,然后删除包含 message 在内以及后面所有的 message + console.log("retryMessage", id) + const index = conv.value.messages.findIndex(message => message.id === id); + const pastMessage = conv.value.messages[index-1] + conv.value.inputText = pastMessage.text + if (index !== -1) { + conv.value.messages = conv.value.messages.slice(0, index-1); + } + console.log(conv.value.messages) + sendMessage(); +} + const autoSend = (message) => { conv.value.inputText = message sendMessage() @@ -677,6 +715,12 @@ watch( border-radius: 8px; text-align: center; background: #FFF0F0; + margin-bottom: 10px; + cursor: pointer; + } + + .searching-msg { + color: var(--gray-500); } }