夜雨聆风学习资料网

ARTICLE · 1188941

从“找文档”到“直接提问”:知乎数据库智能客服的 RAG 实践

从“找文档”到“直接提问”:知乎数据库智能客服的 RAG 实践

让开发自助解决常见数据库问题,让 DBA 从重复 oncall 中抽身,也让散落在 Wiki、PDF、Skills 和个人笔记里的经验真正变成团队能力。

数据库团队经常遇到这样一类场景:

开发同学碰到连接超时、慢查询、Redis 热点、TiDB DDL、OceanBase 资源配置等问题,第一反应往往是在群里 @DBA。DBA 接到问题后,需要先问清环境、判断数据库类型,再从 Wiki、运维手册、历史故障报告甚至自己的笔记中翻找答案。

很多时候,问题并不新,答案也并不缺。真正缺少的是一条足够短、足够准、还能说明“答案从哪里来”的知识获取路径。

这正是我们建设“知乎数据库智能客服”的出发点。

一、我们想解决什么问题?

数据库知识天然具有几个特点:专业门槛高、上下文依赖强、更新频率高,而且部分内容涉及高危操作,并不适合对所有人完全开放。

过去,知识通常分散在多个地方:

  • Wiki 中有标准流程,但页面多、层级深;
  • PDF 手册内容完整,却不适合临时检索;
  • DBA Skills 沉淀了平台接口、诊断步骤和安全规范;
  • 故障复盘和个人笔记里有大量实战经验,却很难被团队复用;
  • 群聊中的历史答疑包含上下文,但搜索成本高,结论也可能已经过期。

如果只是把这些资料再集中到一个新的文档库里,并没有真正解决问题。我们更希望用户可以直接用自然语言提问,系统自动完成知识检索、权限过滤、答案组织和来源展示。

因此,项目从一开始就确定了五个目标:

  1. 服务开发同学:覆盖高频、标准化的数据库问题,减少重复咨询和无效 oncall。
  2. 服务 DBA:不再依赖记忆去翻 Wiki、手册和个人笔记,通过一个入口检索团队知识。
  3.  答案可追溯:每次回答都尽量给出来源文档、技能名称和章节,方便核验,而不是只给一个“看起来合理”的结论。
  4.  权限可控制:开发只能检索共享知识,DBA 可以检索包含运维细节和高危操作规范的完整知识。
  5.  知识可治理:文档更新支持预览、激活、回滚,避免新版本一导入就立即影响线上召回。

第一阶段的边界也很明确:它是一个“知识型数据库智能客服”,负责回答问题和提供操作指引,不直接替用户执行生产数据库变更。

二、项目整体架构

整个系统可以分成六个核心层次,以及一条贯穿始终的知识治理链路。

1. 用户与交互层

项目面向两类核心用户:开发和 DBA。

前端采用 Streamlit 构建类聊天界面,用户可以发起新问题、继续历史对话,也可以查看当前角色有权限访问的文档列表。对用户来说,入口是一个熟悉的聊天窗口;对系统来说,每次请求都会携带会话上下文和用户身份。

在正式生产环境中,用户身份应由统一登录、JWT 或身份网关提供,并由后端决定角色。不能只相信前端传来的 role 字段,否则用户可能通过修改请求绕过权限控制。

2. API 与会话编排层

FastAPI 对外提供统一接口,负责接收问题、读取历史对话、调用 RAG 检索与大模型,并把最终回答和引用来源写回会话记录。

当前核心接口包括:

  • /chat:发起问答;
  • /documents:查看当前角色可访问的文档;
  • /conversations:查询历史会话;
  • /health:检查服务状态。

这一层把前端与底层模型、检索逻辑隔离开。未来无论接入企业微信、DBA 数字人还是其他内部平台,都可以复用同一套 RAG 服务。

3. RAG 检索与答案编排层

这是整个项目的核心。

系统先把用户问题转换成 1024 维向量,然后分别执行向量检索和全文检索。两路结果通过 RRF(Reciprocal Rank Fusion,倒数排名融合)合并,得到最终候选知识块。

检索过程中还会同时应用三类过滤条件:

  • is_active:只查询已经激活的知识版本;
  • access_level:根据开发或 DBA 身份过滤可见内容;
  • database_types:在需要时限定 MySQL、TiDB、Redis、OceanBase 等数据库类型。

如果命中了某个 DBA Skill,系统还会自动补充该 Skill 中的“安全规范”“输出规范”“必读”等全局规则,避免关键约束因为没有排进 Top K 而被遗漏。

4. 模型服务层

项目把“检索模型”和“回答模型”解耦:

  • Embedding 模型负责把文档和问题映射到同一个 1024 维语义空间;
  • 大语言模型负责阅读召回的上下文,并生成结构化、可读的中文回答。

Embedding 接口采用 OpenAI 兼容协议,因此既可以接阿里云百炼,也可以切换到公司内网模型。大模型同样通过兼容接口调用内部 Claude 网关。这样可以减少对单一供应商的绑定。

如果知识库完全没有覆盖某个问题,当前策略不是伪造内部结论,而是允许大模型基于通用知识回答,并明确提示“该内容不在内部知识库范围内,需要自行核实”。这里需要特别说明:当前实现是大模型通用知识兜底,并不等于已经实现实时互联网搜索。

5. MongoDB 数据与检索层

MongoDB 同时承担三类职责:

  • 在 knowledge_chunks 集合保存知识块、元数据和 1024 维向量;
  • 维护全文索引和向量索引,执行语义与关键词检索;
  • 在 conversations 集合保存历史会话、回答和引用来源。

这使项目不必再额外拼接“文档数据库 + 独立向量数据库 + 独立搜索引擎”三套系统,知识原文、权限元数据、版本状态和向量可以保存在同一份文档中。

6. 知识生产与更新层

知识来源包括 PDF 运维手册、Markdown 文档、DBA Skills、故障报告和个人笔记。

入库过程会依次完成:文档解析、切分 Chunk、补充数据库类型与权限标签、调用 Embedding、写入 MongoDB 新版本、人工验证,再执行激活。

新版本默认处于 is_active=false 状态,不会立即参与线上检索。只有经过预览和问题集验证后才激活;如果新版本召回效果下降,可以回滚到旧版本。这让知识更新从“一次覆盖”变成了一个可审查、可恢复的发布过程。

三、一条问题是怎样被回答的?

以开发同学提问“TiDB 执行 DDL 一直不结束,应该先检查什么?”为例,一次完整问答会经历以下步骤。

第一步:接收问题和身份

Streamlit 将用户问题、会话 ID、数据库类型和用户身份发送给 FastAPI。后端读取之前的对话历史,用于理解追问中的省略信息。

第二步:生成查询向量

系统调用与文档入库时相同的 Embedding 模型,把问题转换为 1024 维向量。只有查询和文档使用同一个模型、同一套向量空间,语义距离才有比较意义。

第三步:执行权限预过滤

检索不会先找出所有内容再在页面上隐藏,而是在搜索阶段就带上 access_level、is_active 等过滤条件。开发用户只能让共享文档进入候选集合,DBA 专属文档不会参与其向量距离和全文分数计算。

第四步:走两条检索路径

向量检索通过 $vectorSearch 查找“意思相近”的内容。即使资料里写的是“在线 DDL 卡住”,而用户问的是“DDL 一直不结束”,系统仍可能找到相关章节。

全文检索通过 $search 查找关键词、产品名、错误码、参数名和命令。对于 ERROR 9007、tikv_gc_life_time 这类精确词,全文检索通常比单纯语义检索更可靠。

第五步:融合排序

向量相似度和全文相关性分数的量纲不同,不能简单相加。当前项目采用 RRF,根据一个知识块在两路结果中的排名计算融合分:

RRF 分数 = Σ 1 / (60 + rank)

如果一个知识块在语义检索和关键词检索中都排在前列,它就会获得更高的最终排名;如果只被其中一路召回,也仍然有机会进入结果。

第六步:补齐规则并组装上下文

系统截取最终 Top K 知识块,并补充命中 Skill 对应的安全规范与全局规则,然后把来源、章节和正文整理成模型上下文。

第七步:大模型生成答案

大模型依据检索到的资料生成回答。Prompt 明确要求:优先使用内部资料,不编造接口和参数;区分知识库结论与通用知识;涉及高危操作时必须保留二次确认和安全提示。

第八步:返回答案、来源并保存历史

最终结果不仅包含自然语言答案,也包含来源 Skill、章节和文件。问题与回答会写入 conversations,用户可以继续追问,也可以回看历史会话。

四、为什么选择 MongoDB 8.3 作为检索底座?

传统 RAG 架构经常需要同时维护关系数据库、全文搜索引擎和向量数据库。对于一个内部知识客服,这会带来更多数据同步、权限一致性和运维成本。

在面向生产的方案中,我们选择 MongoDB 8.3,把知识文档、元数据、向量、会话记录和检索能力放在同一个技术体系中。

1. mongod 与 mongot 各自负责什么?

mongod 保存业务文档:原始文本、Embedding 数组、数据库类型、访问级别、版本、激活状态以及历史会话等。

mongot 是独立的 Search/Vector Search 进程,基于 Apache Lucene 构建全文索引和向量索引。它通过 Change Stream 持续同步 mongod 中的数据变化,并把索引段保存在专用存储中。应用只连接 mongod;当聚合管道中出现 $search 或 $vectorSearch 时,mongod 会把检索请求转发给 mongot。

这种设计把事务性文档存储与搜索计算分开,同时保留统一的数据模型和访问入口。

2. 向量检索如何工作?

文档入库时,每个 Chunk 都会生成一个 1024 维向量,并与原文和元数据一起保存。向量索引使用 cosine 相似度,查询时通过 $vectorSearch 执行近似最近邻搜索。

MongoDB Vector Search 的 ANN 检索使用 HNSW(Hierarchical Navigable Small Worlds)结构,不需要逐条扫描全部向量。项目还会设置 numCandidates,先扩大候选范围,再取最终 Top K,以在检索延迟和召回率之间取得平衡。

向量检索擅长理解语义,但它并不天然擅长所有精确匹配。例如错误码、实例名、配置参数和 SQL 关键字只差一个字符,含义就可能完全不同。因此它不能单独承担数据库知识检索。

3. 全文检索解决什么问题?

全文索引覆盖知识块正文、章节标题和知识来源名称。$search 可以对这些字段进行词法检索,并使用基于 Lucene 的相关性评分找出包含精确术语的内容。

它尤其适合错误码、命令名、参数名、数据库对象名和产品版本号等场景。向量检索负责“意思相近”,全文检索负责“字面准确”,两者互补。

4. 混合检索为什么更适合数据库问答?

数据库问题往往同时包含自然语言意图和精确技术实体。例如“TiDB 扩容后 Region 一直不均衡,怎么检查 schedule-limit?”既需要理解“扩容后不均衡”的语义,也需要准确识别配置项 schedule-limit。

当前项目分别执行 $vectorSearch 和 $search,再由 Python 使用 RRF 融合排名。这是当前代码已经实现并验证过的链路。

MongoDB 8.3 还提供数据库原生融合能力:$rankFusion 可以按排名合并多路结果,$scoreFusion 在 8.3 中已经 GA,可以对不同检索分数归一化、加权后再融合。后续可以把当前应用层 RRF 下沉到 MongoDB 聚合管道,减少应用侧拼装逻辑,并进一步评估不同权重和重排策略。

需要注意的是,Search/Vector Search 索引通过 Change Stream 异步更新,因此属于最终一致。文档写入 mongod 成功,并不代表它已经立刻可以被向量或全文检索命中。知识发布流程应在索引进入 READY、完成检索验证后,再把新版本视为正式可用。

五、权限不是页面上的一个角色开关

数据库知识中可能包含管理接口、故障处置步骤、账号信息规范和高危变更流程,因此权限必须进入检索链路本身。

项目把知识分成两类:

  • shared
    :开发和 DBA 都可以查看的通用知识;
  • dba_only
    :只有 DBA 可以查看的运维细节和高危操作知识。

向量检索与全文检索都会在候选生成阶段应用权限过滤,避免无权内容先被召回、再在展示层隐藏。对外开放时,还需要由可信身份系统把真实用户映射到角色,并记录查询人、命中文档、回答来源和时间,形成完整审计链路。

六、知识库如何持续更新?

RAG 的长期价值不只取决于模型,更取决于知识是否新鲜、准确、可回退。

我们为同一份文档引入版本号和激活状态:

  1. 更新后的文档生成新版本,并以未激活状态写入;
  2. 使用真实问题集预览新版本召回结果;
  3. DBA 审核答案、来源和安全提示;
  4. 验证通过后执行激活版本切换;
  5. 如果线上效果下降,快速回滚到上一版本。

这样,知识更新不再是“删掉旧数据再重新导入”,而是像发布代码一样,有预览、有验收、有切换,也有回滚。

七、项目带来了什么收益?

项目上线使用情况:

对开发:从“找人”变成“先自助”

开发可以直接描述问题,不必先理解文档目录结构,也不必知道答案藏在哪一份手册里。常见问题可以在第一时间获得有来源的处理建议,把真正复杂、需要人工判断的问题再升级给 DBA。

对 DBA:从“重复回答”转向“维护知识”

DBA 不再反复回答同一类问题,也不必在多个系统中来回搜索。更重要的是,个人经验可以逐步沉淀为团队可复用的知识资产,DBA 的时间可以更多投入到复杂故障、容量治理和稳定性建设中。

对团队:形成统一、可追溯的知识出口

同一个问题不再因为咨询对象不同而得到完全不同的答案。来源展示、权限控制、版本管理和回滚机制,让知识的可信度、时效性和使用边界都更清楚。

对平台:建立可复用的数据库智能能力

FastAPI 将检索能力封装成统一服务后,Streamlit 只是第一个入口。未来可以继续接入企业微信机器人、DBA 数字人、工单系统和告警诊断流程,复用同一套知识底座。

项目收益不能只靠主观感受判断。后续可以持续观察以下指标:

  • 开发自助解决率;
  • 被智能客服分流的重复 oncall 数量;
  • 首次获得有效答案的平均时间;
  • 回答来源覆盖率与用户采纳率;
  • 无召回、低质量召回和人工纠正比例;
  • 知识从更新到生效的平均周期。

八、写在最后

数据库智能客服不是简单地给大模型接一个文档目录,也不是让模型代替 DBA 做判断。

它真正要解决的是:如何把分散的专业知识组织起来,如何在正确的权限边界内找到它,如何让答案可验证、知识可更新、错误可回退。

当开发可以先通过智能客服解决常见问题,DBA 可以直接检索团队长期积累的经验,oncall 才有机会从“重复问答”回归到真正需要专业判断的事情上。

从“到处找文档”到“直接问问题”,变化的不只是交互方式,更是数据库知识从个人经验走向团队资产的过程。


延伸阅读

  • MongoDB Search and Vector Search on Self-Managed Deployments
  • MongoDB Vector Search Overview
  • How to Perform Hybrid Search
  • MongoDB 8.3 Release Notes

相关学习资料