青禾光伏智能服务平台

RAG 知识问答与智能工单分流实践

面向光伏行业客户与企业服务人员,整合 RAG 知识问答、FAQ 直出、人工客服和智能工单分流的完整业务实践。

  • RAG
  • FastAPI
  • Milvus
  • React
  • BGE-M3
与技术同行
让清洁的阳光
照亮更多人。
盘腿使用电脑的 Zcoco 与黑色柴犬、银灰色缅因猫Small steps
Bright future.
项目目录
  1. 一、项目概述
  2. 1.1 项目背景
  3. 1.2 项目目标
  4. 1.3 技术架构
  5. 二、整体业务流程
  6. 三、RAG 核心能力
  7. 3.1 文档解析与知识库构建
  8. 3.2 Milvus 混合检索
  9. 3.3 FAQ 直出
  10. 3.4 检索策略与动态路由
  11. 3.5 查询改写与多轮对话
  12. 3.6 核心编排服务
  13. 四、缓存与性能设计
  14. 五、智能工单分流
  15. 5.1 转人工流程
  16. 5.2 BERT 与规则协同
  17. 5.3 紧急程度
  18. 六、客户端业务逻辑
  19. 七、员工智能工作台
  20. 八、权限与数据边界
  21. 九、项目亮点
  22. 9.1 不是“所有问题都做 RAG”
  23. 9.2 稠密与稀疏检索互补
  24. 9.3 答案全程可追溯
  25. 9.4 客户与员工双端闭环
  26. 9.5 本地模型与数据可控
  27. 9.6 生成服务故障时仍能保持核心能力
  28. 9.7 面向生产的缓存失效设计
  29. 十、Web 服务基础设施
  30. 十一、知识库治理与质量闭环
  31. 十二、RAG 基础概念:为什么它适合光伏客服
  32. 12.1 什么是 RAG
  33. 12.2 Embedding 是什么
  34. 12.3 为什么不能只用向量检索
  35. 12.4 Reranker 为什么放在召回之后
  36. 十三、知识入库设计
  37. 13.1 在线检索与离线入库分离
  38. 13.2 文档统一结构
  39. 13.3 父子分块
  40. 13.4 FAQ 与普通文档分集合
  41. 13.5 增量更新
  42. 十四、在线 RAG Pipeline 深入
  43. 14.1 为什么需要 Pipeline
  44. 14.2 Stage 0:输入与权限
  45. 14.3 Stage 1:业务路由
  46. 14.4 Stage 2:查询准备
  47. 14.5 Stage 3:FAQ 快速通道
  48. 14.6 Stage 4:文档混合检索
  49. 14.7 Stage 5:去重与重排
  50. 14.8 Stage 6:证据不足保护
  51. 14.9 Stage 7:统一输出
  52. 十五、Milvus 索引与过滤设计
  53. 15.1 双向量字段
  54. 15.2 HNSW 参数含义
  55. 15.3 中文 BM25
  56. 15.4 权限过滤表达式
  57. 十六、检索事件协议
  58. 16.1 为什么需要事件协议
  59. 16.2 事件顺序
  60. 十七、三级缓存实现细节
  61. 17.1 缓存什么
  62. 17.2 缓存 Key
  63. 17.3 TTL 策略
  64. 17.4 依赖故障降级
  65. 十八、FastAPI 服务层
  66. 18.1 为什么使用异步
  67. 18.2 路由边界
  68. 18.3 统一错误处理
  69. 18.4 启动前置校验
  70. 十九、工单领域模型与状态流转
  71. 19.1 工单核心数据
  72. 19.2 状态机
  73. 19.3 为什么客户不用注册
  74. 二十、智能分流算法
  75. 20.1 输入与输出
  76. 20.2 规则与模型的边界
  77. 20.3 可解释性
  78. 二十一、前端体验设计
  79. 21.1 客户门户
  80. 21.2 检索结果卡片
  81. 21.3 员工工作台
  82. 21.4 数据刷新
  83. 二十二、异常与降级策略
  84. 二十三、项目目录说明
  85. 二十四、典型业务使用路径
  86. 24.1 客户知识问答
  87. 24.2 转人工与智能分流
  88. 24.3 员工工单处理
  89. 24.4 内部知识库
  90. 二十五、完整平台能力
  91. 25.1 内容运营
  92. 25.2 检索质量
  93. 25.3 客服协同
  94. 25.4 运行治理
  95. 二十六、质量评估指标
  96. 26.1 路由指标
  97. 26.2 检索指标
  98. 26.3 回答指标
  99. 26.4 工单指标
  100. 26.5 性能指标
  101. 二十七、Bad Case 闭环
  102. 二十八、安全与隐私
  103. 二十九、总结

青禾光伏智能服务平台:RAG 知识问答与智能工单分流实践

一个面向光伏行业客户与企业服务人员的智能服务平台,将知识库检索、FAQ 直出、意图识别、人工客服和智能工单分流整合为完整业务闭环。

青禾光伏智能咨询门户

一、项目概述

1.1 项目背景

光伏设备涉及组件、逆变器、储能系统、并网设备等多类产品。客户在使用过程中会产生大量专业咨询,例如设备参数查询、告警代码解释、安装规范、功率衰减、质保政策和售后申请等。

传统客服模式主要面临以下问题:

  • 产品资料分散在不同手册中,人工查找效率低;
  • 客户描述不规范,同一个问题可能有多种表达方式;
  • 普通问题和紧急故障混在一起,工单依赖人工判断;
  • 客户转人工后,客服需要重新理解上下文;
  • 企业内部制度和客户产品资料权限边界不清晰;
  • 大模型直接回答容易产生无依据内容,缺少来源追踪。

青禾光伏智能服务平台围绕“知识优先解决,复杂问题智能转人工”的思路,构建客户门户与员工工作台两个业务端。

1.2 项目目标

项目重点实现两个核心能力:

  1. RAG 知识库检索:基于企业授权资料回答光伏产品和内部制度问题,并展示答案来源、问题分类、置信度和处理耗时。
  2. 智能工单分流:客户提交人工咨询后,自动识别问题类型、情绪倾向和紧急程度,为员工提供辅助判断。

1.3 技术架构

层级 技术方案 主要职责
前端 React、TypeScript、Vite、TanStack Query 客户门户、员工工作台、状态轮询与交互
后端 FastAPI、SQLAlchemy、异步接口 用户会话、RAG 服务、工单与权限接口
数据库 PostgreSQL 员工、会话、工单、消息和缓存命名空间
向量数据库 Milvus BGE-M3 稠密向量与内置 BM25 稀疏检索
缓存 进程内缓存、Redis、PostgreSQL 热点数据、检索结果和版本失效控制
AI 模型 BGE-M3、BGE Reranker、本地 BERT 向量化、重排序、意图分类与情绪识别
RAG 生态 LangChain、LangChain Milvus 文档对象、向量库适配与检索编排

二、整体业务流程

平台不是把所有问题都直接送入向量数据库,而是先路由,再决定最合适的处理链路。

flowchart TD
    A[客户输入问题] --> B[业务领域与意图路由]
    B -->|无关问题| C[直接提示业务范围]
    B -->|标准高频问题| D[FAQ 精确/语义匹配]
    B -->|专业知识问题| E[RAG 混合检索]
    D --> F[返回标准答案]
    E --> G[生成有来源的回答]
    F --> H[展示分类来源库置信度]
    G --> H
    H --> I{是否需要人工}
    I -->|| J[继续多轮咨询]
    I -->|| K[填写人工咨询描述]
    K --> L[BERT + 业务规则分析]
    L --> M[生成分类情绪与紧急程度]
    M --> N[进入员工工单队列]
    N --> O[客服接单并回复]
    O --> P[客户在我的咨询查看消息]

这条链路体现了三个业务原则:

  • 能拦截的不检索:天气、闲聊等无关问题在第一层结束,避免无意义召回。
  • 能直出的不生成:高频标准问题优先走 FAQ,速度更快、答案更稳定。
  • 需要检索的必须可追溯:专业问题使用知识库回答,并携带来源信息。

三、RAG 核心能力

3.1 文档解析与知识库构建

产品手册、FAQ 和企业内部制度先转换为统一文档对象,并保留标题、章节路径、页码、知识库类型和文档编号等元数据。

文档切分采用父子块结构:

  • 父块保留较完整的章节语义;
  • 子块用于精确检索,降低无关上下文;
  • 检索命中子块后,可以通过父块补充完整语境;
  • 内容哈希用于识别文档变化并避免重复入库。

知识库按业务权限分为两类:

  • 产品知识库:产品参数、故障处理、安装维护、售后与质保资料;
  • 企业内部制度库:入职流程、内部服务规范和企业管理制度。

客户只能检索产品知识库,员工登录后才能访问两个知识库。

3.2 Milvus 混合检索

单独使用向量检索擅长理解语义,但对型号、告警码和精确参数不一定敏感;单独使用关键词检索能够匹配专有名词,却难以理解用户的自然表达。

平台在 Milvus 中同时建立:

  • Dense 稠密向量:由 BGE-M3 生成,负责语义召回;
  • Sparse 稀疏向量:使用 Milvus 内置 BM25,负责关键词、型号和告警码匹配。

检索采用加权混合策略,将两路结果融合。权重以语义检索为主,同时保留关键词检索对设备型号和故障码的敏感度。

flowchart LR
    Q[用户问题] --> D[BGE-M3 Dense 向量]
    Q --> S[Milvus BM25 Sparse 向量]
    D --> R[加权融合]
    S --> R
    R --> T[候选文档]
    T --> X[BGE Reranker 精排]
    X --> C[高相关上下文]
    C --> A[答案生成与来源引用]

3.3 FAQ 直出

FAQ 与普通文档使用独立检索集合。问题进入知识链路后先判断是否可以命中高置信度 FAQ:

  • 命中时直接返回经过审核的标准答案;
  • 不命中时再进入普通产品文档检索;
  • FAQ 返回仍携带分类、来源库和置信度;
  • 标准答案不依赖生成模型,即使生成服务暂时不可用也能稳定工作。

例如“逆变器报警代码含义”可直接命中 FAQ,而“QH-620 组件额定功率是多少”则进入产品手册检索。

3.4 检索策略与动态路由

平台为三种典型问题建立了不同的处理路径:

问题类型 示例 处理方式
无关问题 今天天气怎么样? 领域路由直接拦截,不访问知识库
FAQ 问题 逆变器报警代码含义 FAQ 高置信度直出
知识检索问题 QH-620 组件额定功率是多少? Dense + BM25 混合检索

路由结果同时决定知识库范围。客户查询固定限制为产品资料;员工可以选择产品知识库、企业内部制度库或全部授权知识库。

3.5 查询改写与多轮对话

真实用户可能只输入“这个怎么处理”“还有其他要求吗”等不完整问题。多轮对话需要结合上一轮主题补足当前问题,再进入检索。

平台通过查询准备链路完成:

  1. 清洗用户输入;
  2. 识别是否依赖历史上下文;
  3. 补全产品型号和问题对象;
  4. 生成适合检索的标准查询;
  5. 保留原始问题用于最终回答。

3.6 核心编排服务

RAG 服务负责统一编排:

  1. 校验用户角色和知识库权限;
  2. 执行业务领域与意图路由;
  3. 查询缓存;
  4. 并行检索 FAQ 与普通文档;
  5. 合并、去重并重排候选结果;
  6. 计算检索置信度;
  7. 组织回答和参考来源;
  8. 返回问题分类、来源库、处理耗时与检索过程。

前端通过事件协议接收运行状态,依次展示“开始处理、问题路由、知识检索、答案生成、处理完成”等阶段,避免长时间等待时页面没有反馈。


四、缓存与性能设计

平台围绕知识检索建立三层缓存治理:

  1. L1 进程内缓存:短时间保存知识库命名空间版本,减少重复查询数据库;
  2. L2 Redis 检索缓存:缓存 FAQ、文档和向量结果,降低重复检索开销;
  3. L3 PostgreSQL 版本控制:持久化知识库缓存 Epoch,负责跨进程一致失效。

缓存 Key 不直接保存用户问题明文,而是结合查询哈希、用户角色、知识库范围、模型版本、资料版本和命名空间版本生成。

当知识库更新时,系统提升对应知识库的 Epoch。旧缓存无需全量扫描删除,因为新请求会自然生成新的 Key;如果失效过程失败,当前进程会阻止继续使用可能过期的缓存。

平台只缓存检索结果,不缓存最终生成答案,避免不同用户上下文之间发生答案串用。


五、智能工单分流

5.1 转人工流程

客户点击“联系人工客服”后,需要描述设备型号、故障现象和当前影响。系统创建工单时自动完成分析,然后把工单放入员工工作台。

sequenceDiagram
    participant C as 客户
    participant API as 服务平台
    participant AI as BERT与规则引擎
    participant S as 客服人员
    C->>API: 提交人工咨询
    API->>AI: 意图、情绪、紧急程度分析
    AI-->>API: 分类结果与置信度
    API-->>C: 返回咨询编号
    API->>S: 工单进入待接单队列
    S->>API: 接单并回复
    API-->>C: 我的咨询展示最新消息

5.2 BERT 与规则协同

纯模型分类可能受到短文本、口语表达和训练数据规模影响,因此工单分流采用“BERT 辅助信号 + 业务规则”的组合方式。

  • BERT 识别客户意图;
  • 情绪模型判断积极、中性、负向或强烈负向;
  • 规则识别“停机、冒烟、起火、多次故障”等紧急词;
  • 业务规则结合产品类型确定分类和建议部门;
  • 低置信度结果标记为需要人工复核。

员工端重点展示情绪识别置信度,而不是把较低的意图分类分数作为醒目的业务指标。

5.3 紧急程度

工单按普通、高、紧急三个等级进入队列。涉及安全风险、设备停机或强烈负向情绪的问题会得到更高优先级,帮助客服先处理影响更大的问题。


六、客户端业务逻辑

客户门户采用匿名会话,不要求用户注册账号,降低咨询门槛。

核心功能包括:

  • 产品知识智能问答;
  • 三类典型问题覆盖不同路由;
  • 检索过程实时展示;
  • 问题分类、来源库、置信度和耗时展示;
  • 参考来源展开查看;
  • 联系人工客服并提交咨询;
  • “我的咨询”持续查看客服回复。

匿名身份通过浏览器 HttpOnly Cookie 保存。只要客户继续使用同一浏览器,就可以看到此前咨询和员工回复,同时避免在前端直接保存敏感身份信息。


七、员工智能工作台

青禾光伏员工智能服务工作台

员工登录后进入统一工作台,页面由三部分组成:

  • 左侧工单队列:显示工单状态、紧急程度、问题摘要和分类;
  • 中间对话区:查看客户原始描述、沟通记录并回复;
  • 右侧智能分析:展示客户意图、问题分类、情绪倾向、置信度和处理建议。

员工还可以在产品知识库与企业内部制度库之间切换,在回复客户前快速查找有来源的标准答案。


八、权限与数据边界

平台采用“匿名客户 + 授权员工”两类身份:

能力 匿名客户 授权员工
产品知识库检索 支持 支持
企业内部制度库检索 不支持 支持
创建人工咨询 支持 不适用
查看工单 仅限当前浏览器创建的咨询 可查看工作台工单
回复与处理工单 不支持 支持

员工会话通过安全 Cookie 维护,接口层再次校验身份,不能只依赖前端隐藏菜单实现权限控制。

青禾光伏员工登录界面


九、项目亮点

9.1 不是“所有问题都做 RAG”

系统先判断问题是否属于业务范围,再区分 FAQ 与知识检索。无关问题不检索,标准问题不生成,真正需要专业资料的问题才进入完整 RAG 链路。

9.2 稠密与稀疏检索互补

BGE-M3 理解自然语言语义,Milvus BM25 捕获型号、告警码和精确关键词,两者融合后更适合光伏设备场景。

9.3 答案全程可追溯

用户不仅看到答案,还能看到问题分类、答案来自哪个知识库、置信度、处理耗时和具体资料来源。

9.4 客户与员工双端闭环

项目不止实现一个知识问答页面,还打通了“智能回答—转人工—自动分流—员工接单—持续回复—客户查询进度”的完整业务流程。

9.5 本地模型与数据可控

向量模型、重排序模型、意图模型和情绪模型均可在本地运行,知识库权限由后端控制,适合对内部资料安全有要求的企业场景。

9.6 生成服务故障时仍能保持核心能力

FAQ、混合检索、来源返回、工单分流和本地模型识别不依赖外部大模型。生成服务正常时负责组织自然语言答案;生成服务异常时,系统基于检索证据返回结构化摘要。

9.7 面向生产的缓存失效设计

缓存 Key 同时绑定知识版本、模型版本、角色和知识范围;知识更新通过 Epoch 实现跨进程失效,避免员工和客户命中越权或过期缓存。


十、Web 服务基础设施

后端采用 FastAPI 异步服务,对外提供:

  • 匿名客户与员工会话接口;
  • 知识检索同步接口;
  • 检索事件流接口;
  • 工单创建、列表、详情、接单、回复和解决接口;
  • 健康检查和统一异常响应。

前端使用 React 和 TypeScript 构建,TanStack Query 负责接口状态与缓存,Vite 在开发环境中将 /api 请求代理到后端服务。


十一、知识库治理与质量闭环

RAG 系统不仅需要“能检索”,还必须持续保证知识质量。平台建立以下治理能力:

  • 文档版本管理与增量入库;
  • 重复、冲突和失效内容检测;
  • FAQ 审核与发布时间管理;
  • Bad Case 自动沉淀;
  • 无答案率、命中率、来源正确率和响应耗时评估;
  • 根据评估结果校准路由阈值、召回数量和混合检索权重。
flowchart LR
    A[线上咨询] --> B[收集低置信度与失败问题]
    B --> C[Bad Case 数据集]
    C --> D[分析路由检索与答案问题]
    D --> E[更新资料/FAQ/阈值]
    E --> F[回归评估]
    F --> G{达到质量门槛}
    G -->|| H[发布新知识版本]
    G -->|| D

十二、RAG 基础概念:为什么它适合光伏客服

12.1 什么是 RAG

RAG(Retrieval-Augmented Generation,检索增强生成)可以理解为“先查资料,再组织答案”。与直接让大模型根据参数记忆回答不同,RAG 会先从企业授权知识库中找出相关材料,再把材料作为回答依据。

一个最小 RAG 系统包括四个部分:

  1. 知识源:产品手册、FAQ、安装规范、售后政策和内部制度;
  2. Embedding 模型:把文字转换成可以计算相似度的向量;
  3. 向量数据库:保存向量、原文和元数据,并完成相似内容召回;
  4. 回答服务:组合用户问题与检索材料,生成最终回答。

对于光伏客服,RAG 的价值尤其明显。组件型号、逆变器告警码、额定功率、工作电压等信息具有很强的产品依赖性,不能只依靠通用语言模型猜测。回答必须来自对应型号的正式资料,并向用户展示出处。

12.2 Embedding 是什么

Embedding 会把一段文字映射为高维数值向量。语义相近的文本,其向量在空间中的距离通常更近。

例如:

  • “逆变器出现 E021 告警”;
  • “设备提示绝缘监测异常”;
  • “逆变器绝缘故障怎么处理”。

三句话表面关键词并不完全相同,但表达了相近的问题。经过 BGE-M3 向量化后,它们可以在语义空间中彼此接近,从而召回同一份故障处理资料。

12.3 为什么不能只用向量检索

语义检索并不擅长所有情况。像 QH-620E02152.4V 这类字符串,对业务非常重要,但在向量空间里未必能获得足够高的区分度。

因此项目同时使用 BM25:

  • BGE-M3 负责“意思相近”;
  • BM25 负责“词语精确”;
  • Reranker 负责“在候选中再次精排”。

这三步形成“广泛召回—互补融合—精细排序”的检索漏斗。

12.4 Reranker 为什么放在召回之后

Embedding 检索需要在大量数据中快速找候选,适合使用 Bi-Encoder:问题和文档分别编码,文档向量可以预先保存。

Reranker 通常采用 Cross-Encoder 思路,把问题和候选文档放在一起判断相关性,精度更高但计算成本也更高。因此它只处理召回后的少量候选,而不是遍历全部知识库。

全部知识库
   ↓  Dense + BM25 快速召回
候选 Top K
   ↓  Reranker 精细排序
最终上下文 Top N
   ↓  答案组织
有依据的回复

十三、知识入库设计

13.1 在线检索与离线入库分离

知识库系统包含两条性质完全不同的链路:

  • 离线链路负责读取、清洗、切分、向量化和写入知识库;
  • 在线链路负责接收用户问题、路由、检索和回答。

两条链路必须分离。入库通常耗时较长,还可能遇到文件损坏、表格解析失败、模型资源不足等问题;在线查询则要求稳定且快速,不能在用户每次提问时重新读取和切分全部文档。

13.2 文档统一结构

进入向量库的每个 Chunk 不只保存文本,还保存可用于过滤、展示和治理的元数据:

{
  "document_id": "product/inverter",
  "title": "QH-100K 逆变器故障与运维手册",
  "knowledge_scope": "product",
  "source_type": "doc",
  "heading_path": "故障处理 / E021",
  "page_number": 12,
  "parent_chunk_id": "product/inverter:p08",
  "content_hash": "...",
  "corpus_owner": "solar-demo-v2"
}

这些字段分别解决不同问题:

  • knowledge_scope 控制客户与员工能够检索的资料范围;
  • source_type 区分 FAQ 和普通文档;
  • heading_path 帮助回答展示具体章节;
  • content_hash 用于增量更新与去重;
  • corpus_owner 防止同一 Milvus 实例中的不同项目数据互相影响。

13.3 父子分块

文档切分需要在“召回精度”和“上下文完整度”之间平衡。

Chunk 太大时,一个段落可能同时包含多个主题,向量表达被稀释;Chunk 太小时,虽然命中精确,但答案缺少前置条件和完整步骤。

项目采用父子分块思路:

  • 子块较短,用于检索;
  • 父块保留完整章节;
  • 子块命中后,通过父块恢复完整语境;
  • 标题路径与页码跟随 Chunk 保存。

对于光伏手册,这种方式可以避免只召回“请断开设备”一句,却遗漏前文中的适用型号、安全条件和后续检查步骤。

13.4 FAQ 与普通文档分集合

FAQ 和普通文档的业务意义不同。

FAQ 是经过审核的标准问答,目标是高置信度直出;普通文档是大段知识材料,目标是为复杂问题提供上下文。因此项目将两者保存到独立 Collection:

  • solar_demo_faq_v2:高频问答;
  • solar_demo_documents_v2:产品与制度正文。

分集合后可以分别配置召回数量、阈值和缓存时间,也便于统计 FAQ 命中率。

13.5 增量更新

服务启动或知识发布时,会计算当前语料版本:

语料版本 = 项目标识
         + Embedding 模型版本
         + Reranker 模型版本
         + 全部文档内容摘要

系统比较当前知识块 ID 与 Milvus 中已有 ID:

  • 新 ID 执行新增;
  • 已存在且未变化的 ID 保留;
  • 已删除文档对应的旧 ID 清理;
  • 模型或语料版本变化后,缓存 Key 自动变化。

这样避免每次启动都清空并重建全部集合,也不会删除同一 Milvus 中不属于本项目的数据。


十四、在线 RAG Pipeline 深入

14.1 为什么需要 Pipeline

在线问答不是一个“搜索函数”,而是由多个阶段组成的业务流水线。Pipeline 的价值是让每个阶段只有一个明确职责,并可以单独观察、替换和降级。

青禾平台可以抽象为以下阶段:

flowchart TD
    S0[Stage 0 输入校验与身份范围] --> S1[Stage 1 业务领域路由]
    S1 -->|无关| OUT[业务范围提示]
    S1 --> S2[Stage 2 查询准备]
    S2 --> S3[Stage 3 FAQ 检索]
    S3 -->|高置信命中| FAQ[标准答案直出]
    S3 -->|未命中| S4[Stage 4 普通文档混合检索]
    S4 --> S5[Stage 5 融合去重与重排]
    S5 --> S6[Stage 6 上下文与答案构建]
    S6 --> S7[Stage 7 引用置信度与统一响应]

14.2 Stage 0:输入与权限

入口首先校验:

  • 问题不能为空且不能超过长度限制;
  • 当前身份是匿名客户还是员工;
  • 客户请求强制限制为 product
  • 员工请求可以使用 productinternalall
  • 请求 ID、开始时间和事件通道已建立。

权限范围在检索前写入过滤条件,而不是检索后再删结果。这样内部制度内容不会先被召回到客户请求的内存上下文中。

14.3 Stage 1:业务路由

路由是整个系统最重要的成本控制点。

对于“今天天气怎么样”这类问题,如果直接执行 RAG,向量库总能找到某些表面相关的词,例如文档中的“现场天气”,最终产生看似有来源但答非所问的结果。

正确方式是在第一层判断它是否属于光伏产品、安装、故障、售后或制度范围。无关问题直接返回可解释提示,并明确说明没有执行知识检索。

14.4 Stage 2:查询准备

用户问题可能包含口语、错别字和上下文指代。查询准备阶段负责:

  • 去除无意义空白与重复符号;
  • 标准化设备型号;
  • 保留告警码、功率和电压等关键实体;
  • 必要时根据历史问题补全指代;
  • 生成适合 Dense 与 BM25 的查询文本。

多轮查询改写将历史问题、当前指代和关键实体合并为独立可检索的问题,同时保留原始输入用于回答展示。

14.5 Stage 3:FAQ 快速通道

FAQ 快速通道承担确定性回答。命中后可以跳过普通文档检索和生成模型:

用户问题
  → FAQ 缓存
  → FAQ 混合检索
  → 阈值判断
  → 标准答案 + FAQ 来源

它的业务优势是低延迟、低成本、可审核和可预测。

14.6 Stage 4:文档混合检索

未命中 FAQ 后,服务并行执行 Dense 与 BM25 检索。Milvus 使用加权 Ranker 合并结果,Dense 与 Sparse 权重分别为 0.55 和 0.45。

Dense 权重略高,是因为客户问题多为自然语言;Sparse 仍保持较高比例,是因为光伏场景包含大量型号、数字和故障码。

14.7 Stage 5:去重与重排

不同检索通道可能召回同一段内容。系统以文档 ID、父块 ID 和内容摘要识别重复结果,避免同一来源在上下文中出现多次。

随后由 Reranker 对“问题—文档”对进行精排,最终只选择高相关内容进入答案上下文。

14.8 Stage 6:证据不足保护

向量数据库总能返回“最相近”的结果,但最相近不等于足够相关。因此系统必须设置证据阈值。

当没有可靠资料时,回答应明确表示:

当前授权知识库中未找到可靠依据。请补充产品型号、故障码或具体问题,也可以转人工咨询。

这比利用低相关文档拼凑答案更符合企业客服要求。

14.9 Stage 7:统一输出

无论走无关路由、FAQ 直出还是普通文档检索,最终都转换成统一响应:

{
  "answer": "...",
  "question_classification": {
    "category": "设备故障"
  },
  "knowledge_bases": ["产品FAQ库"],
  "retrieval_confidence": 0.95,
  "processing_time_ms": 14.1,
  "pipeline": "FAQ direct answer",
  "sources": []
}

统一契约让前端不必为每条路线实现完全不同的页面。


十五、Milvus 索引与过滤设计

15.1 双向量字段

Milvus Collection 同时维护:

  • dense:BGE-M3 向量;
  • sparse:BM25 内置函数产生的稀疏向量;
  • text:原始 Chunk;
  • 动态元数据字段:知识范围、标题、父块等。

Dense 字段使用 HNSW 索引,适合近似最近邻搜索;Sparse 字段使用 BM25 索引。

15.2 HNSW 参数含义

项目使用:

M = 16
efConstruction = 200
查询 ef = 64
  • M 决定图中节点连接数量,越大通常召回更好,但占用更多内存;
  • efConstruction 影响建索引质量和耗时;
  • 查询 ef 控制搜索范围,越高通常召回越好,但延迟也会上升。

这些参数不是固定真理,生产环境需要根据知识规模、并发量和 Recall@K 评测结果调整。

15.3 中文 BM25

BM25 依赖分词。Collection 使用中文分析器,让“逆变器报警代码”“额定功率”等中文词组能够参与稀疏检索。

与在应用层自行维护另一套稀疏向量相比,Milvus 内置 BM25 可以让数据写入、索引和混合搜索在一个系统中完成,减少双库同步复杂度。

15.4 权限过滤表达式

检索时构造类似下面的过滤条件:

corpus_owner == "solar-demo-v2"
and knowledge_scope in ["product"]

员工查询全部授权资料时,范围可以扩展为:

knowledge_scope in ["internal", "product"]

过滤值必须经过转义,并且只能来自服务端白名单,不能直接拼接任意用户输入。


十六、检索事件协议

16.1 为什么需要事件协议

RAG 请求可能涉及模型加载、向量化、两路召回、重排和答案构建。如果前端只有一个旋转图标,用户无法判断系统是否正在工作。

平台为检索定义结构化事件:

事件 含义 前端表现
start 请求已接收 建立当前回答卡片
status 当前处理阶段变化 展示路由、检索、生成进度
token 产生部分回答内容 逐步追加文本
end 最终结果完成 展示元数据和参考来源
error 请求失败 显示可读错误并结束等待

16.2 事件顺序

sequenceDiagram
    participant UI as React 客户端
    participant API as FastAPI
    participant RAG as RAG Service
    UI->>API: 建立检索事件连接
    API-->>UI: start
    API->>RAG: query(message, scope, role)
    RAG-->>UI: status:意图路由
    RAG-->>UI: status:知识检索
    RAG-->>UI: status:答案生成
    RAG-->>UI: token:部分文本
    RAG-->>UI: end:答案、来源、置信度

异常也必须转换成 error 事件并正常收口,避免前端一直停留在“正在检索”。


十七、三级缓存实现细节

17.1 缓存什么

平台缓存 FAQ、文档检索结果和可复用向量,不缓存最终自然语言答案。

最终答案可能受到用户角色、对话上下文和回答策略影响;盲目缓存答案容易造成串话、过期回答或权限泄漏。检索结果更稳定,也更容易通过版本进行治理。

17.2 缓存 Key

缓存 Key 由稳定 JSON 序列化后计算 SHA-256 摘要,参与计算的字段包括:

  • 缓存种类;
  • 问题哈希;
  • 授权知识范围;
  • 用户角色;
  • 语料和模型版本;
  • 各知识范围的 Epoch。

同一个问题由客户查询和员工查询会产生不同的 Key,从缓存层继续保持权限隔离。

17.3 TTL 策略

不同数据的变化频率不同:

缓存对象 示例 TTL 原因
FAQ 检索 30 分钟 标准答案稳定、重复率高
普通文档检索 15 分钟 兼顾命中率与资料更新
Embedding 60 分钟 计算成本高、相同文本结果稳定
L1 Epoch 3 秒 快速感知失效,同时降低数据库压力

17.4 依赖故障降级

Redis 不可用不应该让知识问答整体不可用。缓存读取异常按 Miss 处理,系统继续访问 Milvus;同时清理进程内 Epoch,避免使用不确定状态。

如果知识失效写入 PostgreSQL 失败,对应 Scope 会被当前进程暂时阻止使用缓存,优先保证一致性。


十八、FastAPI 服务层

18.1 为什么使用异步

RAG 请求包含大量 I/O:

  • 访问 PostgreSQL;
  • 访问 Redis;
  • 访问 Milvus;
  • 等待模型或生成服务;
  • 向前端推送事件。

FastAPI 的异步模型可以在一个请求等待外部服务时处理其他连接,提高并发利用率。对于本地模型推理这类阻塞任务,项目通过工作线程执行,避免阻塞主事件循环。

18.2 路由边界

接口按领域拆分:

  • /api/auth:匿名会话、员工登录和会话查询;
  • /api/knowledge:同步知识问答;
  • 检索事件接口:向前端输出阶段状态;
  • /api/tickets:客户创建和查看本人咨询;
  • /api/staff/tickets:员工查看、接单、回复和解决;
  • /api/health:服务健康检查。

18.3 统一错误处理

后端不会把数据库异常堆栈或模型路径直接返回浏览器,而是转换为统一、可读的错误结构。每个请求保留 Request ID,方便后续关联日志。

18.4 启动前置校验

服务启动时执行以下前置检查:

  • 环境变量是否完整;
  • PostgreSQL、Redis 和 Milvus 是否可连接;
  • Collection 是否存在或允许初始化;
  • 本地 BGE 与 BERT 模型目录是否完整;
  • 员工初始密码是否仍为默认值;
  • 知识库语料是否为空。

平台提供模型资源检查与初始化脚本,避免服务启动后第一次请求才发现模型缺失。


十九、工单领域模型与状态流转

19.1 工单核心数据

一张工单不仅保存客户描述,还包含:

  • 业务编号;
  • 匿名客户会话;
  • 问题摘要与类别;
  • 当前状态;
  • 紧急程度;
  • 客户意图与模型置信度;
  • 情绪标签与情绪置信度;
  • 分流依据和建议部门;
  • 是否需要人工复核;
  • 创建时间和消息记录。

19.2 状态机

stateDiagram-v2
    [*] --> 待接单: 客户创建咨询
    待接单 --> 处理中: 员工接单
    处理中 --> 处理中: 客户/员工发送消息
    处理中 --> 已解决: 员工标记解决
    已解决 --> [*]

后端校验状态转换。例如未接单工单不能直接以“处理中员工”的身份回复,已解决工单不能继续追加普通消息。

19.3 为什么客户不用注册

为了降低咨询门槛,客户身份默认使用匿名浏览器会话:

  • 首次访问自动创建会话;
  • 会话 ID 保存在 HttpOnly Cookie;
  • 客户接口只返回该会话创建的工单;
  • 员工回复后,客户刷新“我的咨询”即可查看。

匿名会话还可以绑定手机号、订单号或企业客户账号,在保持低门槛的同时支持跨设备查询。


二十、智能分流算法

20.1 输入与输出

分流输入是客户原始问题,输出不仅是一项类别,而是一组业务信号:

{
  "category": "设备故障",
  "department": "技术支持",
  "urgency": "urgent",
  "intent": "product_quality_issue",
  "emotion": "strong_negative",
  "emotion_confidence": 0.81,
  "needs_review": false,
  "reason": "识别到设备停机与强烈负向情绪"
}

20.2 规则与模型的边界

BERT 适合识别自然语言类别和情绪,但企业规则更适合处理强确定性的业务条件。

例如:

  • 出现“起火、冒烟、触电”时,安全规则应直接提升优先级;
  • 出现“设备已停机、多次无法发电”时,不应只依赖情绪分数;
  • 模型置信度低时,规则可以给出保守分类并标记复核;
  • 用户语气激烈但问题只是进度催促时,情绪和业务分类应分别保存。

20.3 可解释性

员工工作台不只展示“AI 判定紧急”,还展示判定依据。客服可以根据原始描述、情绪标签和业务规则做最终判断。

AI 在这里承担辅助决策,而不是绕过员工自动做不可逆业务操作。


二十一、前端体验设计

21.1 客户门户

客户首页采用清洁能源与地球视觉,主区域聚焦一个问题输入框。用户不需要理解 RAG、向量库或模型,只需要知道“可以查询产品使用、安装维护和故障排查”。

三个预设问题分别覆盖典型路由:

  1. 无关问题展示路由能力;
  2. FAQ 问题展示标准答案直出;
  3. 产品参数问题展示知识库检索。

21.2 检索结果卡片

答案卡片分为四层:

  • 首层是自然语言答案;
  • 第二层是问题分类、来源库、置信度和耗时;
  • 第三层是本次处理 Pipeline;
  • 第四层是可以展开的参考来源。

这种结构兼顾阅读效率和结果核验:用户先读答案,需要核验时再查看来源。

21.3 员工工作台

员工页面强调信息密度:

  • KPI 快速了解待接单、处理中和已解决数量;
  • 队列按优先级定位问题;
  • 中间区域专注沟通;
  • 右侧 AI 面板提供判断依据;
  • 产品知识库和内部制度库通过侧边栏切换。

21.4 数据刷新

工单列表使用低频增量轮询同步队列状态,轮询过程中通过写入锁和 Revision 防止员工正在回复时旧请求覆盖新状态;会话消息使用 WebSocket 推送,减少无变化请求并保证客服与客户之间的实时沟通。


二十二、异常与降级策略

企业 AI 应用不能只考虑“所有依赖都正常”的路径。

故障场景 平台策略
生成模型服务不可用 使用 FAQ、检索摘要与本地模型维持核心服务
Redis 不可用 缓存按 Miss 处理,继续访问检索服务
Milvus 不可用 返回明确的 RAG 环境不可用提示
BERT 模型不可用 使用业务规则完成保守分流
检索证据不足 不生成确定性答案,引导补充信息或转人工
员工未登录 后端拒绝内部知识库和员工工单接口
事件流异常 输出 error 事件,前端结束加载状态

降级原则是:可以降低智能程度,但不能伪造高置信度、泄露权限范围或让页面无限等待。


二十三、项目目录说明

qinghe-solar-service-platform/
├─ apps/
│  ├─ api/                  # FastAPI 服务、RAG 与工单接口
│  │  ├─ src/solar_api/
│  │  │  ├─ auth/           # 匿名与员工会话
│  │  │  ├─ core/           # 配置、数据库、异常
│  │  │  ├─ demo/           # 工单与智能分流
│  │  │  ├─ demo_documents/ # 产品资料与内部制度示例
│  │  │  ├─ rag_service/    # Milvus 混合检索
│  │  │  ├─ rag_cache.py    # 三级缓存治理
│  │  │  └─ rag_events.py   # 检索事件协议
│  │  └─ tests/
│  └─ web/                  # React 客户端与员工端
├─ packages/
│  ├─ ml_runtime/           # 本地模型资源注册与加载
│  └─ rag_core/             # 文档切分与模型 Provider
├─ scripts/                 # 初始化、模型检查与接口导出
├─ docs/                    # 设计文档和博客图片
├─ docker-compose.yml       # 基础服务编排
├─ .env.example             # 安全环境变量模板
└─ README.md

二十四、典型业务使用路径

以下使用路径能够串联平台的全部核心能力。

24.1 客户知识问答

  1. 打开客户门户;
  2. 点击“今天天气怎么样?”;
  3. 说明无关问题在入口被拦截,没有执行检索;
  4. 点击“逆变器报警代码含义”;
  5. 展示 FAQ 直出、95% 置信度和来源库;
  6. 点击“QH-620 组件额定功率是多少?”;
  7. 展示混合检索结果、资料来源与处理耗时。

24.2 转人工与智能分流

输入:

我的逆变器持续报警,已经重启多次仍然无法正常发电,现场设备已停机,请尽快处理。

提交人工咨询后,展示咨询编号和“我的咨询”页面。

24.3 员工工单处理

  1. 登录员工工作台;
  2. 查看刚创建的紧急工单;
  3. 展示问题分类、情绪倾向和情绪置信度;
  4. 接单并回复;
  5. 回到客户页面查看回复;
  6. 员工标记工单已解决。

24.4 内部知识库

员工进入企业内部知识库,查询“新人入职流程”,展示员工权限可以访问内部制度,而客户不能访问。


二十五、完整平台能力

平台围绕内容、检索、客服协同和运行治理形成四组完整能力。

25.1 内容运营

  • 建立文档上传与审核后台;
  • 支持 PDF、Word、Markdown 和结构化表格;
  • 建立产品、型号、版本和适用区域元数据;
  • 制定 FAQ 负责人和有效期。

25.2 检索质量

  • 建立真实问题评测集;
  • 分别统计 FAQ 命中、文档召回和答案质量;
  • 校准不同问题类别的检索阈值;
  • 加入多轮查询改写和实体识别;
  • 建立 Bad Case 周期。

25.3 客服协同

  • 接入企业员工账号;
  • 支持客服组、技能组与排班;
  • 增加工单 SLA、超时提醒和升级;
  • 引入 WebSocket 实时消息;
  • 增加服务评价和质检。

25.4 运行治理

  • 完善日志、指标和链路追踪;
  • 增加限流、熔断、超时与重试;
  • 建立知识库灰度发布和回滚;
  • 对敏感信息进行脱敏;
  • 完成备份、恢复和容量评估。

二十六、质量评估指标

RAG 系统不能只凭“看起来回答得不错”验收。

26.1 路由指标

  • 无关问题拦截准确率;
  • FAQ 路由准确率;
  • 知识库范围选择准确率;
  • 应转人工问题的召回率。

26.2 检索指标

  • Recall@K:正确资料是否出现在前 K 个结果中;
  • MRR:正确资料首次出现的位置;
  • 型号与告警码命中率;
  • 不同知识库的越权召回数;
  • 无答案问题的错误召回率。

26.3 回答指标

  • 答案是否由来源支持;
  • 引用是否指向正确文档;
  • 关键参数是否准确;
  • 信息不足时是否正确拒答;
  • 回答完整性与可操作性。

26.4 工单指标

  • 分类准确率;
  • 紧急问题召回率;
  • 情绪识别准确率;
  • 人工复核比例;
  • 首次响应时间;
  • 工单解决时长。

26.5 性能指标

  • FAQ P50/P95 延迟;
  • 文档检索 P50/P95 延迟;
  • 缓存命中率;
  • 模型加载时间;
  • 并发请求成功率;
  • 外部依赖降级成功率。

二十七、Bad Case 闭环

线上低置信度、用户转人工和客服纠正结果都是高价值数据。

Bad Case 处理流程:

  1. 自动记录问题、路由结果、召回文档和最终答案;
  2. 判断错误发生在路由、检索、重排还是回答阶段;
  3. 由业务人员补充正确分类和正确资料;
  4. 决定修复 FAQ、文档、规则、阈值或模型;
  5. 将案例加入回归数据集;
  6. 新版本发布前重新执行评估。

不能把所有失败都归因于模型。很多问题来自资料缺失、Chunk 边界错误、元数据不完整或阈值配置不合理。


二十八、安全与隐私

客户咨询可能包含电话、地址、设备序列号和现场照片。正式系统需要:

  • 在输入区域提示不要提交不必要的敏感数据;
  • 日志中避免记录完整 Cookie、密码和 Token;
  • 客户接口按匿名会话隔离工单;
  • 内部制度检索强制员工鉴权;
  • 缓存 Key 包含角色与知识范围;
  • 上传资料经过类型、大小和恶意文件检查;
  • 对导出、分享和删除操作保留审计记录。

本项目的权限边界从检索前开始执行,并贯穿数据库查询、缓存和结果返回,而不是只通过前端菜单控制。


二十九、总结

青禾光伏智能服务平台的核心价值,不是简单地接入一个大模型,而是把企业知识、检索策略、权限控制和客服业务真正连接起来。

对于客户,它提供了更低门槛、更快且有依据的产品咨询服务;对于员工,它减少了查找资料和判断工单的时间;对于企业,它建立了一套可持续治理、可追溯、可扩展的智能服务基础。

平台完整覆盖真实文档上传、知识库后台管理、WebSocket 实时消息、客服自动分配、服务评价、数据统计与生产环境部署,并通过质量评估和 Bad Case 闭环持续优化业务效果。