一次回答的链路
公开教程 · 无需登录

一次回答的链路

本页把前几页接成一条链。一轮提问要经过十一步:先确定会话用的是哪个智能体、本次命中哪个技能,再从该智能体绑定的材料里取依据,把角色与依据分别装进两条消息送入生成,最后落库。检索落空不会让链路终止,只是清空引用列表。

1从请求到持久化

顺序取自服务端处理一轮提问的那一个方法:前七步都在准备输入,第八步起才开始产生输出。

1 取会话按会话编号与当前用户读取,再比对班级
2 取智能体读会话选定的智能体,再比对班级
3 取候选集只取该智能体绑定且已启用的技能
4 选技能在候选集内按适用条件打分,至多一个
5 记问题首轮用提问前 24 字改写标题,随后落库
6 检索只在绑定材料内检索,取前 4 条
7 筛切片去掉空正文与学科不符的,再依次编号
8 推 meta状态、技能与引用列表先到
9 组消息角色与技能进系统消息,资料进用户消息
10 生成逐段推 delta
11 收尾助手消息落库,推 done

第 5 步把提问先落库,是为了让下一轮读到的历史里一定包含本轮提问。第 8 步刻意排在组消息之前:引用列表与技能名先发出去,页面立刻能显示出处,而读历史、拼消息、等首字这三段耗时都藏进同一次首字延迟里。第 7 步筛完可能一条不剩——链路不因此中断,引用列表以空数组下发,第 10 步照常生成。

步骤落在哪一层失败时怎么返回
1–2 切会话与智能体两次数据库查询不存在或跨班 → 404
3–5 取技能、落库提问一次查询,两次写入数据库不可用 → 503
6 检索调用检索服务服务不可用 → 503
7–9 筛切片、推 meta、组消息全部在进程内没有失败分支
10–11 生成与收尾对话网关,随后一次写入首片之前 → 503;之后只能补一条 error 事件
第 9 步之后再出错,HTTP 状态码已经是 200,改不回来;能返回 404 与 503 的只有前七步。这条分界线落在第一个事件产生的那一刻——上一页讲过它的成因,这里给出它在这一条链上的确切位置。

2有依据与无依据的两种口径

检索命中与否,改变的是消息的措辞与引用列表,而不是这段回答要不要写。

有切片 绑定材料内检索 两条消息 系统消息:优先引用,要求标 [1] 用户消息:附上编号资料 调用对话网关 正文可带 [1] 引用列表非空 没有切片 检索结果为空 两条消息 系统消息:不得写出编号 用户消息:一句说明 调用对话网关 正文剥掉 [n] 引用列表为空 两条路都走到同一次生成,差别只在消息措辞与引用列表
检索是否命中,决定的是回答里有没有编号与出处,而不是这段回答要不要写。落空时模型仍按角色与技能作答,只是不得写出 [1] 这样的编号,也不得把回答写成整段的「资料中未找到相关内容」。

3编号、落库与回溯

生成之后还有几件事要做对:编号怎么发、落空后怎么清、这一轮凭什么可回溯。

编号连续,不跳号

先把空正文的切片剔除,再依次编号。若先编号再剔除,回答里的 [2] 就会指向引用列表里已经不存在的条目。每条资料截断 800 字,避免单条过长挤占上下文。

落空时还要剥掉编号

无依据那一支的模型输出,在推给浏览器之前会先删掉所有 [n] 形式的编号,免得出现指向不存在出处的引用。系统消息里也已写明不要编号,两道措施取其一都够用,叠在一起是不去指望模型每次都听话。

助手消息连同当次证据一并持久化

助手消息除正文外,还写入引用列表与本次命中的技能名。done 事件返回这条消息的编号。事后可按会话回放:这一轮用的是哪个智能体(记在会话行上)、命中了哪个技能、引了哪几份材料、材料属于哪个班。

生成中途失败的降级处理

生成过程中若已产出若干片段才失败,则以已生成的内容收尾并持久化;一个片段都未产出时,才向上返回错误。增量推送开始后状态码已不可变更,只能以 error 事件收尾。

流式回答的 meta 里,状态字段恒为「ok」:这一轮有没有依据,从引用列表是否为空即可读出,不必再借状态区分。第 4 课的问答接口则把「没有依据」单列成一个独立状态——同一件事,两条链路各有一套口径。