feat:优化流式输出,增加临时多轮对话记录

This commit is contained in:
2026-09-29 09:55:17 -07:00
parent 6a38a5f15e
commit a89a458c22
10 changed files with 153 additions and 23 deletions
+1
View File
@@ -50,6 +50,7 @@ class IntentNode(BaseNode):
# 汇总用户需求、澄清历史、交互上下文和大屏摘要,作为意图判断的输入
return {
"prompt": context.prompt,
"history": context.history,
"clarification_history": context.clarification_history,
"context": context.context.model_dump(mode="json", exclude_unset=True),
"screen_summary": {
+27 -5
View File
@@ -2,6 +2,7 @@
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.output_parsers import StrOutputParser
from langgraph.config import get_stream_writer
from app.clients.llm import get_llm
from app.processor.base import BaseNode
@@ -18,8 +19,16 @@ class QANode(BaseNode):
# 获取普通对话模型,问答只需文本回答,不绑定结构化输出协议
llm_client = get_llm()
# 异步调用模型,结合用户问题、当前大屏和澄清记录生成回答
llm_res = await llm_client.ainvoke(
try:
# 图执行上下文中通过 custom 流逐段推送回答,独立调用节点时没有写入器
writer = get_stream_writer()
except RuntimeError:
writer = None
parser = StrOutputParser()
parts: list[str] = []
# 异步流式调用模型,结合用户问题、当前大屏和澄清记录生成回答
async for chunk in llm_client.astream(
[
# 系统消息提供稳定的问答规则和回答边界
SystemMessage(content=QA_SYSTEM_PROMPT),
@@ -28,10 +37,23 @@ class QANode(BaseNode):
content=state["input_context"].model_dump_json(exclude_unset=True)
),
]
)
):
# 从每个片段提取文本,兼容文本内容块,工具调用等无文本片段会得到空串
delta = parser.invoke(chunk)
if not delta:
continue
parts.append(delta)
if writer is not None:
writer(
{
"type": "answer_delta",
"message_id": state.get("message_id"),
"delta": delta,
}
)
# 从模型响应中提取文本,兼容文本内容块,并去除回答首尾的空白
answer = StrOutputParser().invoke(llm_res).strip()
# 拼接完整回答,并去除首尾的空白
answer = "".join(parts).strip()
# 如果没有有效文本,抛出异常,避免将空回答标记为处理完成
if not answer:
raise ValueError("问答模型未返回文本回答")