企业知识库 · 生产级复盘

近万份文档接入AI,最难的不是模型

四个人、三个半月、8600多份文档。Demo一周能跑,真正可信的企业知识库却要穿过数据、检索、证据和反馈的峡谷。

近万份企业文档通过知识生产线接入AI的文章封面

项目启动时,目标听起来很简单:把散落在 Confluence、Word、Markdown 和内部论坛里的技术资料统一接入大模型。

以后技术同学遇到问题,不用翻十几个目录,也不用在群里等待老员工回复。

我们一开始估计,一两周应该能跑起来。

确实,一两周以后,Demo 能问答了。

但直到四个人前后投入近三个半月,系统才真正具备部门级使用的条件。

8600+项目文档
3700+嵌入图片
4人核心团队
3.5月上线周期
企业知识库有五次危险的错觉:以为清洗完了、以为入库完了、以为搜到了、以为能返回文字就够了、以为上线就是结束。

以下数字来自本次项目复盘口径。真正值得复用的,不是某个固定参数,而是每一步如何判断"真的完成了"。

第一次错觉:文件能打开,就等于数据能使用

盘点之后,我们找到 8600 多份文档。97% 在 5000 字以内,少量超长文档接近 3 万字;还夹着 3700 多张图片。

真正麻烦的不是格式多,而是噪音已经和知识长在了一起:

  • 页面 ID、上传时间、下载次数和编辑记录;
  • "上次编辑者"一类尾注;
  • 浏览器兼容提示和附件下载提示;
  • 论坛回复区标记、纯数字行和失效链接;
  • 同一制度的多个历史版本。

这些内容直接进入向量库,系统不一定报错。它只会在用户提问时,安静地返回一堆看起来相关、实际毫无价值的结果。

我们先抽样 50 份,让大模型辅助识别重复噪音模式,再把稳定模式沉淀为清洗规则。全量运行、人工抽检、补规则,再运行。

这个循环做了五六轮,累积 40 多条规则,脚本迭代三十多个版本。最终回看,数据清洗占了项目约 65% 的工时。

企业知识库最重的工作,不是把知识送进 AI,而是先决定什么有资格被称为知识。

我们还为每份文档保留两种产物:Markdown 版本供机器切分入库,格式干净的 Word 版本供用户查看引用原文。

机器吃什么,和人看到什么,不必是同一个文件。

第二次错觉:文档入库了,AI 就知道它能回答什么

清洗后的元数据只有文件名、目录和分类。但用户不会按照文件名提问。

他会问"MQTT 怎么配置",真正的文档却可能叫《数据采集通讯模块使用说明》。

我们让大模型为每份文档补充三类语义元数据:

  1. 一句话摘要;
  2. 5—8 个关键技术术语;
  3. 3—5 个"这份文档能够回答的问题"。

用户的问题和预生成问题往往属于同一种语言,而文件标题属于归档语言。把知识从"文件叫什么"改写成"它能解决什么",检索才开始接近真实使用方式。

但入库阶段还有一颗很贵的雷:项目中途把 Embedding 维度从 768 改为 1024 后,原有 collection 不能继续使用,8600 多份文档必须重新向量化和入库。

从那以后,我们把 Embedding 模型版本、向量维度、清洗规则、分块策略、内容哈希和入库时间写进数据契约。

模型不是换一个接口就结束了。任何会改变向量空间的调整,本质上都是一次数据迁移。

第三次错觉:检索命中了,答案就一定在上下文里

系统上线前出现过一个特别反直觉的 Bad Case:日志明明显示正确文档已被召回,大模型却回答"未找到相关信息"。

排查后发现,为每个切片附加的全文摘要与大量泛化问题高度相似,长期占据 Top-K;真正包含配置参数和表格的正文切片,反而被挤到了截断线外。

系统"搜到了正确的文档",但没有把"包含答案的那一段"交给模型。

最后我们采用父子文档式的连带召回:先找到高相关切片,再用文档标识拉回相关兄弟切片,按顺序重组后交给生成模型。

摘要切片霸榜导致答案漏掉以及父文档连带召回的对比图
文档命中,不等于答案证据进入了模型上下文。

这不代表所有命中都要拉回全文。超长手册仍需控制上下文预算,可只扩展邻近章节或采用章节级父子索引。

必须分开评估:文档命中率,以及答案证据进入上下文的比例。

第四次错觉:参数越大,效果越好

我们从真实问答中整理了 300 个代表性问题,并标注正确答案来自哪份文档。

案例评测中,Top-5 向量检索配合连带召回,Recall@5 达到 94%,300 个问题命中 282 个;加入 Rerank 后达到 99.3%,命中 298 个。

但第一次对 Top-50 候选重排,单次请求耗时达到 12.6 秒。准确率很好,用户体验已经死了。

回看评测发现,大部分正确答案本来就在 Top-20。把重排候选从 50 降到 20 后,耗时降到约 2.8 秒,召回仍保持在 99% 以上。

这不是证明"20 是最佳参数",而是说明生产系统必须同时看三张表:

  • 召回是否足够;
  • 延迟是否可接受;
  • 多出来的准确率是否值得计算成本。

企业不是在参加模型比赛,而是在交付一段可用的业务体验。

第五次错觉:能返回文字,就完成了知识问答

技术文档里有 3700 多张截图。界面操作、报错现场、接线方法和架构关系,很多时候一张图比五段解释更有效。

POC 阶段,我们把图片转成 Base64 塞进响应。它能工作,但体积膨胀、难以缓存,响应也变得笨重。

MVP 阶段改为对象存储:清洗时提取图片、生成稳定地址并建立映射;回答返回前转换图片引用;浏览器负责缓存,存储层可以独立迁移。

另一个关键问题是引用。答案如果不能让用户点回格式完整的原文、看到版本和上下文,就很难建立信任。

企业知识库的交付物应该是:答案 + 证据片段 + 原文入口 + 文档版本 + 数据时间。

真正的知识库,是上线后才开始学习

我们在消息数据中记录原始问题、改写问题、召回文档与分数、各阶段耗时、用户反馈和最终引用。

用户每一次点踩,都是一条免费的 Bad Case 标注。

但只有把问题、召回证据、回答和反馈串在一起,这条标注才有用。只记录"用户不满意",团队仍不知道错在数据、检索、生成,还是文档已经过期。

企业知识库从清洗增强检索验答案到反馈的完整闭环
不是等系统成熟后再收反馈,而是依靠反馈让系统逐渐成熟。

三个半月之后,我们重新定义了"项目完成"

一套 RAG 系统能回答问题,不代表企业知识库已经完成。我们现在会用六个条件验收:

  1. 可追溯:每个答案能回到原文、版本和证据;
  2. 可拒答:没有足够证据时,不自信补全;
  3. 可评测:有固定问题集、Recall、正确率和延迟基线;
  4. 可更新:新文档、变更文档和失效文档可增量处理;
  5. 可治理:权限、有效期、责任人和冲突规则明确;
  6. 可迭代:Bad Case 能定位到链路环节并进入修复队列。

至于是否使用 LangChain、LlamaIndex,或者选择哪一种向量库,反而排在后面。

框架适合快速验证,长期运行则需要足够的可观测性和链路控制。你可以用框架,也可以自建,但必须能回答:

这一条错误答案,究竟在哪一步变坏的?

最后

近万份文档接入大模型,最让人意外的不是工程量大。

而是系统越接近生产,模型在项目中的存在感反而越小。

真正决定结果的是:文档是否干净,知识是否有效,证据是否完整,评测是否持续,错误是否有人修。

开源 RAG 框架让知识库 Demo 变得很容易。但企业最终购买的,不是一个能聊天的搜索框。

而是一套持续回答三个问题的知识生产线:这条知识从哪里来?现在还有效吗?答错了怎么修?

如果你的知识库已经上线:最近 30 天的错误回答中,有多少条已经定位到具体文档和具体链路环节?

如果没有答案,系统可能只是"能用",还远没有进入"可信"。

案例口径说明:文中的文档数量、工时、评测结果、模型与技术参数来自用户提供的项目复盘材料,用于呈现该案例的工程取舍,不应直接作为其他企业的容量规划或选型结论。

常见问题 · FAQ

这篇文章主要讲什么?

四个人用三个半月把8600多份企业文档接入大模型:真正困难的不是模型,而是数据清洗、证据召回、评测、图片与反馈闭环。

「就等于数据能使用」具体怎么做?

盘点之后,我们找到 8600 多份文档。97% 在 5000 字以内,少量超长文档接近 3 万字;还夹着 3700 多张图片。 真正麻烦的不是格式多,而是噪音已经和知识长在了一起: 页面 ID、上传时间、下载次数和编辑记录; "上次编辑者"一类尾注; 浏览器…

「AI 就知道它能回答什么」具体怎么做?

清洗后的元数据只有文件名、目录和分类。但用户不会按照文件名提问。 他会问"MQTT 怎么配置",真正的文档却可能叫《数据采集通讯模块使用说明》。 我们让大模型为每份文档补充三类语义元数据: 一句话摘要; 5—8 个关键技术术语; 3—5 个"这份文档能够回答…

「答案就一定在上下文里」具体怎么做?

系统上线前出现过一个特别反直觉的 Bad Case:日志明明显示正确文档已被召回,大模型却回答"未找到相关信息"。 排查后发现,为每个切片附加的全文摘要与大量泛化问题高度相似,长期占据 Top-K;真正包含配置参数和表格的正文切片,反而被挤到了截断线外。