Files
prop-ai-hr/docs/20260718/问师傅多轮会话与原始资料交付设计.md
T

8.1 KiB
Raw Blame History

问师傅多轮会话与原始资料交付设计

状态:代码、自动化、本地真实 HTTP、本地 390×844 移动端交互和生产基础发布验证已完成;生产正式账号多轮、真机文件权限与正式业务验收仍须分别记录。

目标:让“问·数字师傅”能理解本次连续对话中的指代,并在当前授权范围内交付命中的原文件或操作视频。

1. 当前事实与问题

升级前,mobile-uni/src/pages/user/sop/index.vue 只在页面内展示消息列表,每次文字或附件查询只提交当前问题,服务端没有可用的对话上下文。

因此升级前的能力是“微信式界面 + 单轮无状态 RAG”,不是多轮智能会话。典型失败包括:

  • 用户先问“自动扶梯困人怎么办”,再说“把这个 SOP 原文件给我”,第二句无法确定“这个”指什么;
  • 用户说“有没有操作视频”,系统仍按普通知识问答检索,可能返回另一份语义相近但无关的 SOP;
  • 命中文档后只有引用片段,缺少经过再次授权校验的原文件或视频入口。

2. 第一版目标与非目标

第一版完成:

  1. 内部登录用户拥有 30 分钟不活跃过期的短期会话;页面可显式“新对话”。
  2. 使用现有 chat 模型把追问改写为可独立检索的问题,并输出 QA、FILE、VIDEO、DATA_TOOL 四类意图。
  3. 改写后的问题继续走现有租户、调用应用、主体授权交集和 RAG 链路。
  4. 文件/视频只从当前命中且仍有权限的知识附件中返回;下载时再次校验权限。
  5. 模型、会话表或附件不可用时明确降级,不编造上下文、链接或文件。

第一版不做:

  • 跨天长期记忆、用户画像记忆或对话向量库;
  • 对外 API_TOKEN 调用端的有状态会话;
  • 自动执行任意数据库查询、自然语言转 SQL;
  • 把用户上传的本次图片/视频自动写入共享知识库;
  • 仅凭语义相似度把未命中的文件伪装成“原文件”。

3. 会话数据

新增单表 aihr_knowledge_conversation,只保存一个会话的压缩 JSON,不拆消息表:

字段 作用
tenant_id、app_id、user_id 会话隔离键,全部由服务端身份解析
conversation_id 客户端持有的随机会话 ID
version 乐观并发版本
context_json 最近最多 6 轮的脱敏问题、截断答案、引用标题/文档 ID
expires_time 30 分钟不活跃过期时间
create_time、update_time 审计时间

约束:单个用户问题最多 600 字、单个答案最多 800 字、送入模型的会话上下文最多 6000 字;服务端至多每 5 分钟惰性批量清理 500 条过期记录。唯一键为 tenant_id + app_id + user_id + conversation_id。客户端不能传租户、应用或用户身份。

4. 查询契约

内部 POST /api/knowledge/query 和 POST /api/knowledge/query-media 增加可选字段:

{
  "conversationId": "01J...",
  "contextVersion": 3
}

响应在现有字段上增加:

{
  "conversationId": "01J...",
  "contextVersion": 4,
  "intent": "FILE",
  "rewrittenQuery": "自动扶梯困人应急操作 SOP 原文件",
  "resources": [
    {
      "attachmentId": 123,
      "title": "自动扶梯困人应急操作 SOP.pdf",
      "type": "FILE",
      "contentUrl": "/api/knowledge/resources/123/content"
    }
  ]
}

旧客户端不传会话字段时继续按无状态查询处理。外部 POST /api/open/knowledge/query 保持无状态,并忽略或拒绝会话字段。

5. 处理流程

内部登录与应用解析
  → 计算租户 + 应用 + 主体的有效知识空间
  → 读取本人未过期会话并校验 contextVersion
  → 现有 chat 模型 temperature=0 输出 rewrittenQuery + intent
  → QA/FILE/VIDEO:在有效空间内执行现有混合检索
  → DATA_TOOL:只执行既有白名单工具及角色/项目范围校验
  → FILE/VIDEO:把命中 docId 映射为当前空间的附件资源
  → 返回答案、引用、资源和新 contextVersion
  → 脱敏截断后更新最近 6 轮会话

模型输出必须使用固定 JSON 契约。JSON 解析失败或模型不可用时,以原问题检索,并用关键词规则只做保守意图判断;不能从历史上下文猜测缺失主体。

6. 原文件和视频安全

新增认证接口 GET /api/knowledge/resources/{attachmentId}/content。每次下载必须重新计算当前租户、调用应用、用户/角色与知识空间授权,并确认附件仍属于有效空间,然后才通过现有 OSS 服务流式返回内容。

响应只暴露业务附件 ID、标题、类型和受控接口地址,不暴露 ossId、对象存储 key、原始 OSS URL 或服务器路径。权限被撤销、文件被解绑或附件不存在时立即拒绝;对话中曾经命中过不能覆盖下载时的实时授权。

视频意图只返回视频类型附件;没有视频时明确回答“当前授权资料中未找到相关视频”,不把 PDF、图片或用户本次上传的视频替代成知识库操作视频。

7. 并发与降级

  • 客户端提交旧 contextVersion 时返回冲突,避免两个请求互相覆盖上下文。
  • 会话不存在或过期时,从空上下文继续当前问题,并返回新的版本。
  • 会话持久化失败时保留当前单轮 RAG 能力,同时不声称已理解前文。
  • RAG 无证据时沿用 noEvidence=true;文件/视频意图无附件时返回空 resources 和明确说明。
  • 原始资料接口失败不回退到公开 URL、跨空间附件或模型生成链接。

8. 移动端交互

问师傅页维护当前 conversationId/contextVersion,消息仍只作当前页面展示。顶部提供“新对话”,清空页面消息和会话标识。答案卡增加原文件/视频资源卡,点击时复用现有鉴权文件下载能力;页面卸载或资源替换时释放本地 blob URL。

需要验证文字和语音追问、模型失败、会话过期、并发冲突、无文件、无视频、授权撤销、重新登录和超大字号。微信式外观不再作为“有记忆”的完成证据。

9. 验收用例

最小连续对话:

  1. “自动扶梯困人怎么办?”返回有依据的 SOP 答案和引用。
  2. “把这个 SOP 原文件给我。”rewrittenQuery 指向同一主题,只返回当前授权附件。
  3. “有操作视频吗?”只返回同一主题的视频;不存在时明确无视频。
  4. 点击资料可下载;撤销空间授权后,同一链接立即拒绝。

安全与回归还需覆盖:跨用户/跨租户会话不可读、旧版本冲突、30 分钟过期、模型关闭、OSS 缺失、视频类型过滤、外部 API 保持无状态、旧客户端单轮查询不回退。

完成结论分为:代码实现、自动化测试、本地 HTTP、移动端视觉与交互、生产部署、生产真实多轮、正式业务验收;这些层级不得互相替代。

10. 当前验证记录

  • 后端定向合同与服务测试 21/21 通过;移动端完整单元测试 80/80、类型检查和 H5 生产构建通过。
  • 本地手机号真实登录后完成“报修第一步 → 把对应原文件给我 → 有对应操作视频吗”三轮:上下文版本依次递增,第二轮路由为 FILE 并下载受保护原文件,第三轮无视频时返回空资源和明确说明;旧版本请求返回 409。
  • 390×844 H5 已实际操作登录、两轮追问、资料卡点击和“新对话”;资料卡请求命中受保护内容接口,未发现遮挡、溢出或底栏覆盖。
  • 2026-07-18 已发布功能提交 064816a7:生产 JAR/H5 与本地产物哈希一致,wygj-aihr.service 为 active,必需 schema 35/35,19 张发布表排序规则 19/19 对齐。
  • 生产 390×844 H5 已打开“问”页并点击“新对话”,页面明确显示新会话提示,未发现遮挡、溢出、底栏覆盖或控制台错误。
  • 未使用正式短信 OTP 在生产重放认证态三轮及下载;因此上述只是生产基础发布验证,不等于生产真实多轮、真机文件权限验证或正式业务验收。