llm_ask/docs/superpowers/specs/2026-04-30-llm-qa-system-te...

13 KiB
Raw Permalink Blame History

大模型智能问答客服系统 · 技术方案(腾讯云 ADP 版)

日期: 2026-04-30
版本: v1.0
面向对象: 技术评审、开发实施、运维部署
技术栈: Python / FastAPI / Vue3 / Element Plus / 腾讯云 ADP / 腾讯云 SMS / 腾讯云 COS / PostgreSQL / Redis


一、方案结论

本项目采用「腾讯云 ADP 提供知识库、文档解析、检索、生成和引用;自研业务系统提供账号、权限、会话、审计和调用代理」的架构。

不再自研文档解析、OCR、切片、向量化、召回、重排和引用对齐。自研系统只保留企业应用必须具备、且 ADP 不适合直接承担的能力:

  • 手机号短信验证码登录、JWT、账号禁用和角色控制
  • 用户会话和问答消息长期留存
  • ADP SSE 接口代理,避免 bot_app_key 暴露到浏览器
  • 文档上传、标签、密级、解析状态和审计管理
  • 基于角色的知识库标签过滤
  • Token / PU 用量记录、限额和告警

该路径能显著降低 RAG 自研风险,尤其适合财务制度、报销流程、操作手册等复杂文档问答场景。


二、系统边界

2.1 ADP 负责

能力 说明
文档解析 PDF、Word、Excel、图片等文档解析包含 OCR 和结构化处理
知识切片 按 ADP 应用配置完成切片、索引和向量化
知识检索 RAG / Agentic RAG、多轮检索、召回和重排
答案生成 由 ADP 应用绑定模型、Prompt 和工作流
引用来源 通过 SSE reference 事件返回文档、片段、URL 等来源信息
文档 OpenAPI 文档上传、列表、详情、修改、删除、解析重试、预览等
多模态理解 截图通过 Markdown 图片 URL 传入 content,由 ADP 识别

2.2 自研系统负责

模块 说明
认证与用户 手机号 + 短信验证码登录,管理员创建账号,角色和禁用状态
权限治理 将用户角色转换为 ADP custom_variables,控制可检索标签范围
会话留存 保存会话、问题、答案、引用、模型、Token、PU 消耗
SSE 代理 后端持有 bot_app_key,统一鉴权、限流、转发和错误处理
文档管理 包装 ADP 文档 API叠加业务字段、标签校验和审计日志
统计审计 用户用量、热门问题、失败请求、未命中问题、费用统计

三、总体架构

用户浏览器Vue3 + Element Plus
        |
      HTTPS
        |
      Nginx
        |
FastAPI 业务后端
  |-- 认证模块:手机号 / 短信验证码 / JWT / Refresh Token
  |-- 用户权限模块:角色 / 账号禁用 / KB 标签规则
  |-- 会话模块:会话列表 / 消息落库 / 引用落库
  |-- 对话代理模块POST 流式接口 -> ADP SSE
  |-- 文档管理模块:透传并包装 ADP 文档 OpenAPI
  |-- 审计计量模块Token / PU / 错误 / 操作日志
        |
        |-- PostgreSQL业务数据
        |-- Redis验证码、限流、Token 黑名单
        |-- 腾讯云 COS文档上传中转、截图临时存储
        |
        +-- 腾讯云 ADP
              |-- 知识库:文档、标签、切片、索引
              |-- 应用模型、Prompt、工作流、检索配置
              |-- 对话接口:/v1/qbot/chat/sse
              +-- 文档管理 API

四、认证与账号设计

4.1 登录方式

  • 唯一登录方式:手机号 + 短信验证码
  • 手机号格式:默认中国大陆 +86,字段预留 country_code
  • 自助注册:默认关闭
  • 账号创建:由管理员后台创建用户,指定姓名、手机号、角色和状态

4.2 验证码规则

  • 6 位数字验证码
  • Redis 保存5 分钟有效
  • 同一手机号 60 秒内不可重复发送
  • 同一手机号 24 小时最多 10 次
  • 同一 IP 每小时最多 10 次
  • 单 IP 单小时超过 5 次后要求图形验证码

4.3 Token 规则

  • Access TokenJWT2 小时有效
  • Refresh Token7 天有效,只保存哈希值
  • 管理员禁用账号后,现有 Token 加入 Redis 黑名单并立即失效
  • Refresh Token 支持主动吊销和单用户全量吊销

五、文档管理设计

5.1 采用路线

采用「自研后台包装 ADP 文档 OpenAPI」路线。业务管理员不直接进入 ADP 控制台,所有文档管理都在本系统完成。

这样做的原因:

  • 统一产品体验
  • 能叠加部门、密级、上传人、审计状态等业务字段
  • 能在上传前强制校验标签和权限
  • 后续切换底层 RAG 服务时,前端接口可保持稳定

5.2 核心 ADP 接口

接口 用途
DescribeStorageCredential 获取 COS 临时上传凭证
SaveDoc 文件上传完成后保存到 ADP 知识库
ListDoc 查询文档列表
DescribeDoc 查询文档详情和解析状态
ModifyDoc 修改文档属性和标签
RenameDoc 重命名文档
DeleteDoc 删除文档
RetryDocParse 重试解析失败文档
StopDocParse 停止解析任务
GetDocPreview 获取文档预览
DescribeSegments 查询切片,供调试和验收使用
CreateQA / ListQA / ModifyQA / DeleteQA FAQ 问答库维护

5.3 上传链路

1. 管理员选择文件
2. 前端调用 /api/docs/upload-credential
3. 后端鉴权,调用 ADP DescribeStorageCredential
4. 前端使用临时凭证直传 COS
5. 前端调用 /api/docs/save提交文件 URL、名称、密级、标签
6. 后端校验标签,调用 ADP SaveDoc
7. 后端写入 documents_meta 和操作日志
8. 前端轮询 /api/docs/{id},展示解析状态

5.4 标签与密级

第一期只使用一个强制标签维度:

level = public | internal | confidential

建议规则:

  • employee 可检索:publicinternal
  • admin 可检索:publicinternalconfidential
  • 文档上传和修改时必须填写 level
  • 未打标签文档不得发布到可检索知识库
  • 每日巡检 ADP 文档列表,发现空标签、异常标签立即告警

注意ADP 按标签过滤时,需确认平台对「未打标签知识」的处理策略。为避免权限绕过,本系统必须从业务流程上禁止未打标签文档进入正式知识库。


六、问答代理设计

6.1 前后端交互

不采用 EventSource GET /api/chat/sse?content=... 承载问题内容。原因是问题文本、截图 URL 和上下文可能较长,放在 query 中存在 URL 长度、日志泄漏和编码问题。

推荐采用:

前端 fetch POST /api/chat/stream
  body: {
    conversation_id,
    content,
    image_ids[]
  }

后端 POST ADP /v1/qbot/chat/sse
前端通过 ReadableStream 消费后端返回的流

如浏览器兼容性要求必须使用 EventSource可改成两段式

POST /api/chat/request     创建请求,返回 request_id
GET  /api/chat/sse         只携带 request_id 订阅流

6.2 ADP 请求组装

后端负责组装 ADP 请求体:

{
  "bot_app_key": "${BOT_APP_KEY}",
  "session_id": "adp-session-id",
  "visitor_biz_id": "user-id",
  "content": "用户问题 + Markdown 图片 URL",
  "custom_variables": {
    "level": ["public", "internal"]
  },
  "streaming_throttle": 5
}

其中:

  • bot_app_key 只保存在后端环境变量
  • visitor_biz_id 使用我方用户 ID
  • session_id 与我方 conversations.adp_session_id 绑定
  • custom_variables 由后端根据角色计算,前端不可传入或覆盖

6.3 SSE 事件处理

后端需要处理并落库的事件:

事件 处理方式
reply 增量转发给前端,并拼接完整答案
reference 保存引用来源,前端用于展示来源文档
token_stat 保存输入、输出、PU 消耗
thought 默认不展示给普通用户,可配置为调试模式展示
error 映射为业务错误码,记录日志并返回友好提示

6.4 中断与一致性

  • 用户主动取消时,后端停止读取 ADP 流
  • 浏览器断开时,后端关闭上游连接
  • 若回答未完成,消息状态标记为 interrupted
  • 若 ADP 返回错误,消息状态标记为 failed
  • 完整回答、引用和 Token 统计应在同一事务或可恢复流程中写入

七、截图上传设计

截图不再接入本地 OCR。处理方式

1. 前端上传截图到我方 COS 临时目录
2. 后端生成 5 分钟有效的签名 URL
3. 发送问题时,将图片以 Markdown 格式拼入 content
4. ADP 读取图片并完成多模态理解
5. 我方消息表保存内部对象 key不长期保存临时 URL

安全要求:

  • 截图与正式文档分桶或分目录存储
  • 截图对象设置生命周期,默认 7-30 天清理
  • 临时 URL 只用于本次 ADP 调用
  • 历史会话回看如需展示截图,由我方重新签发短期 URL
  • 敏感截图是否允许进入 ADP 多模态识别,应由甲方合规确认

八、数据模型

users
  id, phone, country_code, external_id, role, is_active,
  display_name, created_at, updated_at

sms_codes
  phone, code_hash, scene, expires_at, attempts

refresh_tokens
  id, user_id, token_hash, expires_at, revoked_at, created_at

token_blacklist
  jti, expires_at

conversations
  id, user_id, title, adp_session_id, created_at, updated_at

messages
  id, conversation_id, role, content, status,
  sources_json, adp_request_id, token_in, token_out,
  pu_cost, model_name, created_at

documents_meta
  id, adp_doc_id, name, level, tags_json, status,
  uploaded_by, uploaded_at, updated_at

role_kb_label_rules
  id, role, label_key, label_values_json, updated_at

usage_log
  id, user_id, conversation_id, message_id,
  token_in, token_out, pu_cost, created_at

operation_logs
  id, actor_id, action, target_type, target_id,
  detail_json, created_at

九、部署方案

9.1 初期部署

单台云服务器
  |-- Nginx
  |-- Vue3 静态资源
  |-- FastAPI + uvicorn workers
  |-- PostgreSQL
  |-- Redis
  +-- systemd 管理服务

外部云服务
  |-- 腾讯云 ADP
  |-- 腾讯云 COS
  +-- 腾讯云 SMS

推荐配置:

  • 4 核 8G 云服务器
  • 系统盘 100G 起
  • PostgreSQL 本机部署
  • Redis 本机部署,maxmemory 256mb
  • Nginx 负责 HTTPS、静态资源和反向代理

9.2 环境变量

DATABASE_URL
REDIS_URL
JWT_SECRET
ADP_BOT_APP_KEY
ADP_API_SECRET_ID
ADP_API_SECRET_KEY
TENCENT_SMS_SECRET_ID
TENCENT_SMS_SECRET_KEY
COS_BUCKET
COS_REGION

.env 文件权限设置为 600,生产环境不提交到代码仓库。


十、测试与验收

10.1 功能测试

  • 手机号验证码登录、刷新 Token、退出登录
  • 管理员创建、禁用、启用用户
  • 文档上传、解析状态轮询、重试、删除
  • 文档标签必填校验
  • 普通用户问答、管理员问答、多轮会话
  • 截图上传并参与问答
  • 引用来源展示和点击预览

10.2 权限测试

测试项 预期
employee 查询 public 文档 可回答
employee 查询 internal 文档 可回答
employee 查询 confidential 文档 不可回答
admin 查询 confidential 文档 可回答
文档未设置 level 不允许保存或发布
前端伪造 custom_variables 后端忽略

10.3 异常测试

  • ADP 超时
  • ADP 5xx
  • ADP 限流
  • 短信发送失败
  • COS 上传失败
  • SSE 中途断开
  • 文档解析失败
  • Token 过期或黑名单命中

十一、风险与对策

风险 影响 对策
ADP 密钥泄漏 外部直接调用并产生费用 密钥只在后端保存,前端永不接触
标签权限失效 用户检索到越权文档 强制标签、后端注入、巡检空标签、权限测试矩阵
ADP 服务不可用 问答能力中断 统一降级提示,记录失败,必要时人工客服兜底
费用不可控 PU 或模型调用超预算 usage_log、单用户日限额、管理员告警
数据合规争议 文档不能进入云端知识库 立项前确认合规口径,必要时采购专属版或私有化
厂商锁定 后续迁移成本增加 LLMProvider 抽象、ADP 配置 YAML 备份、文档源文件自持

十二、人日估算

模块 估算
项目初始化与基础框架 2 人日
认证、短信、Token、限流 5 人日
用户和角色权限 3 人日
ADP 文档 API 包装 5 人日
对话流式代理 5 人日
会话、消息、引用落库 3 人日
截图上传与临时 URL 2 人日
前端登录和主布局 3 人日
前端对话页 5 人日
前端文档管理页 4 人日
前端用户管理页 3 人日
审计和用量统计 2 人日
ADP 应用配置与联调 4 人日
测试、部署、验收修复 5 人日
Buffer 4 人日
合计 约 55 人日

说明:该估算比上一版更保守,主要补入了 SSE 异常处理、权限测试、标签巡检、截图安全和 ADP 联调成本。


十三、参考资料