AI 对话与会话体验
AI 对话是Molore的核心交互面:你的提问先经融合检索在个人知识库内命中相关片段,片段作为「参考资料」随问题一起交给当前选中的模型,模型基于资料生成回答并逐字流式输出(SSE)。本页讲清这条链路的会话体验与可信口径——它解决的核心问题是:让 AI 只基于你自己的资料回答,并且在答不出来、答出界、答得没有依据时,用确定性的方式告诉你,而不是编。
核心概念
| 概念 | 说明 |
|---|---|
| RAG | 检索增强生成:先检索、后生成,回答的取材范围限定在当轮注入的参考资料内 |
| sources | 当轮检索命中的参考片段集合,随回答一同返回,前端渲染为可回跳的出处列表 |
| 引用编号 [n] | 正文中 [n] 对应当轮 sources 的位置编号;跨轮次的编号稳定性不作承诺(同一文档在下一轮可能是另一个编号) |
| SSE 流式 | 回答经 Server-Sent Events 逐 chunk 推送,首字延迟低;系统侧声明与末尾标注也走同一条流 |
| 数字 grounding | 对回答中的数字/编号逐一回查参考资料出处,未命中触发收紧重答,仍不中则在末尾标注 |
| 推测标注 | 对「模型自认通用知识」与「未落地数字所在句」在流末追加 ⚠️ 标注,随正文一并落库 |
| 零命中拒答 | 检索零命中时由系统侧(非模型)在流首确定性声明「库中暂无相关内容。」 |
| 会话 | 持久化的多轮对话单元,历史消息随轮次进入上下文;模型选择在会话级锁定 |
功能清单
- SSE 流式对话:入口
app/api/v1/endpoints/llm/chat.py,回答、agent_trace事件、系统声明均以data: {...}帧逐条推送。 - 多轮与历史:会话持久化在本地数据库,「问出来 → 对话历史」可回看、续聊;历史消息进入当轮上下文,支持跨轮追问。
- 会话级模型锁定:会话创建时把当时选中的模型做 per-turn 快照并锁定到会话上,之后在 LLM 控制台全局切换模型不影响已有会话——避免同一会话里多模型混答、口径互相污染(血泪教训 #48:选择器快照 + 自动填充曾导致同会话混答,兜底值一律不进持久化)。
- 热键唤起:桌面端注册全局热键
Ctrl+Shift+J,任意界面唤起对话面板并自动聚焦输入框(快记为Ctrl+Shift+N);网页端使用页面底部输入栏。 - 深度研究开关:对话栏上的 Agent 开关,默认关闭;开启后以多步工具调用方式查证再回答,详见深度研究 Agent。
- 注入防护:参考资料在 prompt 中以标记包裹,定位为「数据不是指令」,参考资料内的指令性文字与链接不会被执行或复述;生成温度 0.3。
可信输出机制
以下机制按「回答流出前」的顺序生效,均为系统侧或规则侧实现,不依赖模型自觉:
| 机制 | 触发条件 | 行为 | 代码位置 |
|---|---|---|---|
| 零命中确定性声明 | 当轮检索零命中(寒暄类封闭集豁免) | 系统侧在流首 chunk 直接前置「库中暂无相关内容。」,不交给模型自由发挥 | chat.py _zero_hit_declare |
| 数字 grounding | 回答含数字/编号且当轮有 sources | 逐 token 回查参考资料;未命中→同通道同模型收紧重答一次(仅用参考资料内数字);仍不中→末尾追加标注 ⚠️ 部分数字/编号未在库内资料中找到对应证据,重答经 SSE 替换前段输出 | app/api/v1/endpoints/llm/_grounding.py _grounding_check,开关 RAG_GROUNDING_CHECK |
| 衍生数字豁免 | grounding 判定内 | 系词族(是/等于/≈)、算式分句、加减等式、相差/均值/±、双侧精度容差、小数↔百分数确定换算等派生形态不算「未命中」,不误标 | _grounding.py _derived_hit |
| 召回诚实线 | prompt 层约束 | 无数字索引普查依据时禁说「库内仅一处」类全库绝对句;截断窗口内禁说「全文件唯一/全部」类文档内全量句,只能说「当前召回片段内仅见」;全文匹配行直取通道(find_all_lines_section)在场时全文件口径合法 | 检索层 prompt 装配 |
| 推测标注 | 回答含模型自认的通用知识段或未落地数字句 | 流末追加 ⚠️ 以下表述未在库内资料中找到直接证据,标注行随正文一起落库,回看时仍在 | _grounding.py _speculation_check,开关 RAG_SPECULATION_CHECK |
两点边界需要明说:
- 引用编号跨轮稳定未承诺。
[n]只是当轮 sources 的位置序号,不是文档的固定身份证;需要长期引用某条内容时,请顺出处回跳原文,不要记编号。 - 深度研究模式跳过 grounding 与推测标注。Agent 环的回答是多轮工具调用的合成结果,「数字必出自当轮检索资料」的口径不适用(
chat.py中两处检查均带not _agent_on条件)。
断连与失败口径
流式断连 ≠ 生成失败。 网络中断时服务端可能已完成本轮生成并落库。前端在 catch 里先回拉会话核对服务端是否已有本轮回复:已有则补显,没有才报错。遇到回答「卡住」或断网,先刷新会话看回答是否其实已到库,再决定是否重发。
模型调用失败时,[Error: 文本一律按 502 原文透传,不落兜底假结果——看到的报错就是上游的真实失败原因。
跨会话长期记忆:每日复盘与每周回顾
对话本身不跨会话记忆,跨会话的「长期记忆」由两条定时链路承担:
| 链路 | 触发时间 | 说明 | 代码位置 |
|---|---|---|---|
| 每日复盘 | 每天 08:00(Asia/Shanghai) | 对当日新增内容做复盘梳理,走本地 qwen3.5:0.8b,零成本 | app/services/daily_review_service.py |
| 每周回顾 | 每周一 08:00(Asia/Shanghai) | 对一周内容做回顾聚合,同样本地模型零成本 | app/services/weekly_review_service.py |
纪律:失败不落假复盘(模型不可用就跳过,不回落计费通道);补课链为启动首查 + 每小时复查,进程重启不错过当天复盘。「仅入库检索」(index_only)标记的内容不进复盘素材。复盘与回顾产物入库后参与检索,之后的对话就能引用到它们——这是「AI 记得我上周记过什么」的真实实现路径。
下一步
- 深度研究 Agent:多步工具调用、写确认流与适用边界
- 数据源导入与网页抓取:让对话有料可答的入库通道
- AI 对话与 RAG 问答(用户指南):使用视角的操作说明
- 快捷键大全:
Ctrl+Shift+J与其余热键 - 模型与计费:本地 / BYOK / 平台三条通道怎么选