RAG 知识库问答系统怎么搭:文档分块、Embedding、向量库选型全流程拆解

AI实战3个月前发布 aisilink
116 0 0
RAG 知识库问答系统:从文档到答案的完整架构

通用 AI 助手回答不了公司内部的问题。问它报销制度、手头合同里的某个条款,它要么承认不知道,要么一本正经地编一个听起来合理的答案。把文档整个塞进提示词是最直接的解法,但真实的知识库动辄几百上千页,受上下文窗口、延迟和成本三重限制,这条路走不通。检索增强生成(RAG,Retrieval-Augmented Generation)是目前工程上的主流方案:每次提问时只检索最相关的几段内容,连同问题一起交给模型,生成带引用出处的回答。Perplexity、ChatGPT 联网搜索、GitHub Copilot 的代码库检索,以及大公司内部的多数 AI 工具,底层都是这套架构。

本文素材来自 The System Design Newsletter 最新一期长文,作者 Louis-François Bouchard 是《Building LLMs for Production》的作者、Towards AI 联合创始人。原文把”从一堆 PDF 到能回答问题的系统”逐个环节拆开讲,信息密度相当高。这里按中文读者的阅读习惯重新整理,并补充国内落地时的选型参考。

现成工具为什么不够用

Perplexity、带联网搜索的 ChatGPT、接入搜索的 Gemini 都能给出带引用的回答,能力也在快速提升。但它们服务的是公开知识,一旦问题涉及内部文档和受监管数据,局限立刻显现。原文归纳了五条自建的理由:

  • 合规数据出不了自己的边界。个人文件可以传进 ChatGPT 项目里用,但客户记录、合同、医疗档案这类受 HIPAA、GDPR、SOC 2 约束的数据必须留在自己的基础设施内,走自己的权限控制和审计日志。
  • 企业知识不在一个能拖拽上传的文件夹里。真实的知识散落在 Confluence、存着几千份合同的网盘、客服工单系统和内部 wiki 里。现成助手能接入其中一部分,但数据会流出到对方的基础设施、按对方的隐私政策处理;自建系统直接用自己的鉴权读取这些源头,数据不出边界。
  • 检索发生在提问时,答案始终反映最新文档。模型的训练数据有截止日期,文档却在不断更新。RAG 在查询时实时检索,模型训练之后新改的文档照样能用来回答下一个问题,不需要重新训练。
  • 系统知道什么完全可控。文档加进知识库,下一次提问就生效;删掉就不再被引用;更新后回答立刻反映新版本。这种可控性支撑了知识库的筛选、版本管理和审计,也是受监管行业的硬要求。
  • 聚焦检索更准也更便宜。模型基于五段精选内容作答,输入比调动全部训练数据小得多也相关得多,准确率更高;提示词更短,单次调用成本也更低。

整体架构:一条离线管线加一条在线管线

RAG 系统全景架构:离线构建索引与在线回答问题两条管线

图:RAG 全景架构,离线管线建索引,在线管线答问题,两者共享向量数据库

整个系统分两条管线。离线管线负责建索引:解析文档、切分成块、转成向量表示、存进支持按语义检索的数据库,只在初始化或新增文档时运行。在线管线在每次用户提问时运行:把问题转成向量、检索最相关的文本块、连同问题拼成提示词交给模型生成回答。两条管线通过同一个向量数据库衔接。下面按环节展开。

文档摄取:检索质量的第一道关口

文档得先被系统读懂。听起来简单,实际要面对 PDF、HTML、Word、Notion 导出的 Markdown、Confluence 页面、扫描件等一堆格式,每种格式的文本存储方式不同,需要各自的解析器。这一步抽取质量差,后面每个环节都会跟着变差。摄取阶段有五件事要处理:

  • 文本抽取要保留结构信息。标题层级、页码、表格边界要随正文一起抽出来,后面系统才能把引用精确到某份文档的某一节、某一页,而不是只给一个文件名。
  • 表格、代码和图片走单独的抽取通道。表格摊平成一段文字就丢了行列关系;代码去掉缩进和换行就没法读;图片本身不含文本,除非带说明文字或跑 OCR。
  • 扫描件需要 OCR(光学字符识别)。数字版 PDF 里存的是文本,扫描版存的是图片,普通解析器读不出来。Tesseract 是处理清晰扫描件的标准库;低质量图片和复杂版式用视觉语言模型效果更好。代价是 OCR 每页要花几秒,会拖慢摄取速度。
  • 去重。同一份文档存在多个文件夹里会被重复索引,检索时返回一堆相同的块。常规做法是对文档内容做哈希、跳过已索引过的;近似重复(比如同一份合同的不同版本)用模糊文本匹配处理。
  • 剥掉模板噪声。页眉、页脚、导航菜单、版权声明只添噪声不添信息,靠”跨页高频重复”这一特征识别出来,在文本进入下游之前剥掉。

分块:三种切法和起步参数

长文档不能整篇转成一个向量——一个代表 50 页混合内容的向量跟任何具体问题都对不上。所以每份文档要切成小块(chunk),逐块转向量。块的大小是一组权衡:块切得大,上下文充足但向量不够特异;切得小,向量精准但可能缺少回答问题所需的前后文。一个合格的块应当自成一体、只讲一个主题,并带上所在小节的标题和文档名。

固定大小分块、递归分块、语义分块三种策略对比

图:三种文档分块策略对比

主流切法有三种:

  • 固定大小分块:按固定 token 数一刀切,相邻块之间留 50 到 100 个 token 的重叠,保证被切断的句子至少在其中一块里完整出现。这是最简单的方案,适合文章、技术文档这类结构均匀的文本。
  • 递归分块:先按段落切,块还太大再按句子切,再不行才按词切,跟随文档自身的结构而不是硬性边界。LangChain、LlamaIndex 等主流 RAG 库都以它为默认策略。
  • 语义分块:把文档拆成句子,相邻几句编成小组逐组转向量,相邻两组向量差异大的位置就是切分点——向量突变被当作话题切换的信号。话题在段落内部切换而不是段落之间切换时,它比前两种切得准;代价是摄取时每个句组都要调一次 embedding,是三种里最贵的。

原文给的起步配置是递归分块、每块 500 到 800 个 token、重叠 50 到 100 个 token。每个块打上元数据:来源文档、页码、小节标题、最后修改时间——引用功能就靠这些字段实现。起步阶段直接用这套默认参数即可,语义分块留到确认主题边界确实成为瓶颈之后再上。

Embedding:把文字变成可检索的向量

切好的块如果按精确词匹配去搜,会漏掉大部分相关结果——用户提问用的词和文档里的词往往对不上。所以每个块要转成一个固定长度的数字向量,也就是 embedding(向量表示):语义相近的两段文字,向量距离近;主题不同的两段,距离远。这就是为什么搜”重置密码”能找到标题为”账号凭证找回”的文档,尽管两者没有一个词相同。

模型选择上,原文列出的 2026 年常用项是 OpenAI 的 text-embedding-3-large、Cohere 的 embed-v4,开源侧有 bge-large 和 e5-mistral。通常从 API 模型起步,数据驻留、隐私或成本成为约束时再迁到自托管的开源模型;法律、生物医药、金融这类专业领域,领域定制模型一般比通用模型表现好。选型可以参考 MTEB 基准榜单。

Embedding 有三个先天短板,确定检索策略之前要心里有数:

  • 否定词几乎不改变向量。“与华法林相互作用的药物”和”不与华法林相互作用的药物”,一个”不”字把语义完全反转,两句话的向量却几乎一样。
  • 精确标识符没有语义。订单号、错误码、E-4012 这类 SKU 在语义空间里没有位置,相似度检索匹配不了,要靠混合检索补齐。
  • 数值过滤不是相似度问题。“营收超过 500 万美元(约合 3600 万元人民币)的客户”是结构化筛选条件,相似度匹配无能为力,得走结构化检索。

还有一条运营层面的硬约束:给文档块转向量的模型,必须同时用来给用户问题转向量,两者共享同一个向量空间。中途换模型意味着全部语料重新向量化一遍,所以 embedding 模型的选择实际上是一项长期承诺,起步时多花时间测试是划算的。

向量数据库:检索原理与部署选型

向量数据库写入构建索引与查询检索的流程

图:向量数据库的写入与查询流程

转好的向量需要一个支持快速相似度检索的存储系统。向量数据库把每个块的向量连同元数据一起存下来,查询时返回与问题向量最接近的 K 条结果,来源文档、页码、小节标题这些元数据随结果一起返回,引用出处由此而来。

距离通常用余弦相似度衡量,也就是比较两个向量的夹角。最朴素的实现是拿问题向量跟库里每个向量都比一遍,几千条的规模没问题,但成本随库容线性增长,到百万级就撑不住了。生产系统用近似最近邻检索(ANN),用一点召回率换几个数量级的延迟下降,HNSW 和 IVF 是最常用的两类索引。托管型向量库大多把索引选择直接抽象掉,自托管的则允许自己挑索引、调参数。

部署有三条路:

  • 托管服务:Pinecone、Turbopuffer、Weaviate Cloud。基础设施由服务方运营,接 API 即用,适合不想自己运维数据库的团队。
  • 自托管开源:Weaviate、Qdrant、Milvus。跑在自己的基础设施上,配置、扩容、元数据过滤全部自己掌控。其中 Milvus 由国内团队 Zilliz 开源,中文社区资料多。
  • 数据库扩展:pgvector 给 Postgres 加上向量检索能力。技术栈里已经有 Postgres、语料量在百万块以内的团队,pgvector 是更稳妥的起点,不必为向量检索多运维一套独立系统。

基础检索与三种典型失败

在线管线的默认检索只有三步:用同一个 embedding 模型转换问题、对向量库做相似度检索、返回最相似的前 K 条。K 是个权衡参数:太小会漏掉包含答案的块,太大则提示词里塞满无关内容,回答质量下降、成本上升。起步值在 5 到 10 之间,之后拿真实查询测出适合自己语料的取值——预期回答的长度、上下文窗口给检索内容留了多少空间,都会影响这个数。

这套基础检索在”语料均匀、提问直接”的场景下表现不错,但有三种典型失败:

  • 词汇鸿沟。用户说”宕机”,文档写的是”服务中断”;缩写、内部行话、精确标识符也常常落在通用 embedding 模型的理解范围之外。
  • 多跳问题。答案分散在几份语义上互不相似的文档里。比如”CFO 对产品发布怎么表态”需要同时命中财报电话会记录和产品路线图,这两份文档在向量空间里离得很远,单靠相似度检索很难同时召回。
  • 歧义查询。“苹果”既可能指水果也可能指公司,相似度检索会按其中一种理解返回结果,并且不会提示还有另一种可能。

词汇鸿沟和精确标识符问题同源:相似度检索匹配不了它在语义上不理解的词。业界通行的补法是混合检索——在向量检索之外并行跑一路 BM25 关键词检索,两路结果用 RRF(倒数排名融合)之类的方法合并,再用重排序模型精排。原文的付费部分展开讲了混合检索、查询改写、引用策略、RAGAS 评估指标和缓存、权限、监控等生产化议题,免费部分到混合检索开头为止;评估环节的系统性介绍,可以参考本站此前整理的 LLM 评估 29 个核心概念。

国内落地的几点补充

以下是结合国内环境的补充判断,供选型参考:

  • Embedding 模型:OpenAI 和 Cohere 的 API 在大陆无法直接访问,需要相应的网络环境。中文场景更常见的选择是 BGE 系列——北京智源研究院开源,bge-large-zh 针对中文优化,可完全自托管,也顺带满足了前面说的”数据不出边界”;走 API 路线则有阿里通义、智谱等国内厂商的 embedding 服务。MTEB 榜单设有中文分榜 C-MTEB,选中文模型看这个分榜更有参考价值。
  • 不想从零搭管线:Dify、FastGPT、RAGFlow 这几个开源项目已经把”文档上传—分块—向量化—检索—问答”整条链产品化,支持私有化部署,相当于本文这套架构的开箱即用版。原型验证阶段用它们起步比手写管线快得多;需要深度定制分块和检索策略时,再回到自建路线。
  • 起步顺序:已有 Postgres 的团队,从 pgvector 加递归分块跑通最小闭环,再按真实查询暴露出的问题逐项升级混合检索、重排和评估,比一上来就堆满组件更容易定位问题。embedding 模型换一次就要全量重建索引,是整套系统里最不该省测试时间的一个决定。
© 版权声明

相关文章