NickLin
← 项目

企业级知识库(LLM 驱动)

把企业散落在 PDF、Word、表格、网页里的文档,变成一个能语义检索、能多跳推理、能追问出处的知识入口——不是「文档搜索框」,而是「读得懂、引得出、也敢说不知道」的企业知识层。

  • LLM / RAG
  • 文档理解
  • 混合检索
  • 向量 + BM25
  • RRF 融合
  • 重排
  • 引用溯源
  • 私有化部署

产品案例 · 企业级 AI 应用 · 2026

企业级知识库 — 带引用的问答界面

概览

项内容
类型产品案例 · 企业级 AI 应用(LLM 知识库)
场景企业级文档理解、语义检索、智能推理
交互形态上传文档 → 自然语言提问 → 带原文引用的回答 → 多轮追问
输入非结构化文档(PDF / Word / Excel / PPT / 网页)与口语化问题
输出结论 + 引用来源(可点回原文)+ 置信/拒答判定
技术栈FastAPI 服务端 · React 管理后台 · 向量库 + 全文索引 · LLM 推理
部署形态私有化部署,文档与向量数据不出企业内网
管理后台文档库管理、切块预览、检索调试、问答效果评测

场景与需求

企业里真正的知识问题不是「没文档」,是文档在里面,但没人找得到、也没人敢信。典型四条:

  1. 格式太杂——合同是扫描 PDF、流程是 Word、台账是 Excel、制度是网页导出的 HTML,一个搜索框覆盖不了。
  2. 关键词搜不到——员工问「出差超标准了怎么报销」,文档里写的是「差旅费报销标准」,字面不重合,传统全文检索直接漏掉。
  3. 搜到了不敢用——模型开口就答,却给不出处;一旦编了一条制度条款,比搜不到更危险。
  4. 数据不能出去——合同、研发文档、财务台账不允许上传到公有云 API,所以整条链路必须能私有化落地。

这个产品的目标就是把上面四条一次性接住:理解文档 → 找到依据 → 给出可溯源的回答,找不到依据就明说找不到。

它到底做了什么

文档入库 → 解析与结构化切块 → 向量化 + 全文索引
        → 混合召回 → 融合排序 → 重排精选 → 上下文组装
        → LLM 生成带引用的回答 → 溯源校验 → 输出 or 拒答

用户的体感是一句话:「问它,它给你答案,还告诉你这句话是从第几页第几段来的。」

难点与解法

1. 纯向量检索,在企业语料上一定不够用

向量召回擅长「意思相近」,但企业问答里大量存在精确匹配刚需:编号、型号、金额、条款号、专有名词。这些恰好是向量最弱的地方——把「GB/T 1234」和「GB/T 1235」映射到几乎同一个位置。

所以不做单一检索,做混合召回:向量检索 + 关键词检索(BM25)各出一路候选,再用 RRF(Reciprocal Rank Fusion)把两路按排名倒数融合。关键点是不做分数归一化——两路的相似度量纲根本不同,硬归一化等于引入一个假的权重;RRF 只吃排名,天然免疫这个问题。

2. 召回多不等于答得准,中间必须有一道「重排」

混合召回为了保召回率,候选池是刻意放宽的(比如 20 条),但全塞进上下文既贵又吵——噪声片段会把模型带偏。

解法是加一层 Cross-Encoder 重排:把每个候选片段和问题成对送进模型打分,而不是像向量那样各算各的再比距离。代价是慢,所以只对 Top-N 做,用它把 20 条压到 3–5 条真正相关的。召回宽松、精排严格,这两步的分工不能混。

3. 切块策略,决定了这套系统的能力上限

最省事的做法是按固定字数切——结果是表格被切断、条款被拆到两半、标题和正文分家。检索出来全是残句。

改成结构感知切块:先按文档自身的层级(标题 / 小节 / 表格 / 列表)切,只在层级内部再按长度兜底;同时给每个块带上「所属章节路径」的元信息,让一个片段在检索时还能知道自己「从哪来」。块大小也不是一个常数——长制度条文和短 FAQ 需要的粒度不同。

4. 幻觉的真正难点,不是「模型不肯承认不知道」

这是整个项目里最反直觉的一条。

直觉上的解法是「提示词里写上:不确定就说不确定」。但工程上立刻会撞到一堵墙:你没有一个可靠手段去检测它此刻是不是在编。 模型编造的条款读起来和真的条款完全一样,语气一样笃定,格式一样规范。指望模型自我报告,等于把质检交给被质检的人。

所以不从「检测」下手,从流程下手,让它想编也编不出来:

产品的态度是:一个会说「我不知道」的知识库,比一个什么都能答的聊天框有用。

5. 权限必须做在检索层,而不是展示层

企业知识库天然是多租户的:HR 的制度、研发的设计文档、财务的台账,不该互相看见。

风险在于如果只在界面上过滤,等于把不该看的文档召回到了上下文里再藏起来——模型照样可能把内容说出去。

做法是权限前置到检索:过滤条件(部门 / 角色 / 密级 / 文档标签)在查询阶段就进检索过滤,不允许越权的块进入候选池。模型看不到的东西,它就不可能说出来。

6. 把「回答质量」变成可优化的指标,而不是凭感觉

没有评测集,改切块参数、换模型、调 Top-K 全是玄学——这次感觉好了,换个问题又崩了。

所以后台里带一套评测能力:固定一批真实问题 + 人工标注的标准答案/来源文档,每次改动跑一遍,对比召回命中率和回答准确率。先能量化,才谈得上优化。

架构

                ┌───────────────  React 管理后台  ───────────────┐
                │ 文档库管理 · 切块预览 · 检索调试 · 评测看板      │
                └────────────────────┬───────────────────────────┘
                                     │ HTTP
                      ┌──────────────▼──────────────┐
                      │        FastAPI 服务端        │
                      ├─────────────────────────────┤
   入库链路            │ 解析器 → 结构切块 → 向量化   │
                      │ 索引写入(向量 + 全文)      │
                      ├─────────────────────────────┤
   查询链路            │ 查询改写 → 混合召回 → RRF    │
                      │ → Cross-Encoder 重排         │
                      │ → 上下文组装 → LLM 生成      │
                      │ → 引用校验 → 输出 / 拒答     │
                      └──────┬───────────────┬──────┘
                             │               │
                    向量数据库(embedding)  全文索引(BM25)
                             │               │
                        ┌────┴───────────────┴────┐
                        │   PostgreSQL / 对象存储   │
                        └─────────────────────────┘
模块职责
文档解析多格式归一化,扫描件 OCR,表格与层级结构保留
结构切块按文档层级切分,块携带章节路径与来源元信息
混合召回向量检索 + BM25 并行,各自返回排名候选
融合排序RRF 按排名融合,不做跨量纲分数归一化
精排Cross-Encoder 对候选成对打分,压缩到最终上下文
生成与溯源约束引用来源、反查引用合法性、低置信走拒答
权限控制检索阶段过滤,越权内容不进入候选池

检索链路(逐段拆)

阶段做什么为什么这么做
查询处理口语化问题归一化 / 改写用户问法 ≠ 文档写法,需要先拉平
混合召回向量路 + 关键词路并行,各取 Top-N语义覆盖 + 精确命中,互补而非替代
RRF 融合按排名倒数求和重排绕过不同检索器的分数量纲不可比问题
重排Cross-Encoder 精排,保留 3–5 条保召回的前提下把噪声挤出上下文
上下文组装片段 + 来源元信息一并给模型让模型「知道自己在引用什么」
生成 + 校验生成后反查引用是否真实存在出处对不上就重生成 / 降级
兜底分数不足 → 拒答宁可说不知道,不产出猜测

适用场景

其他作品