作者:Felix (Haro 协作整理)
参加 SZDIY 企业级 RAG 分享后,我把其中和企业知识库落地相关的部分重新整理了一遍。相比“把文档丢进向量库,再接一个大模型”的直觉做法,真正可维护的 RAG 系统更像一条长期运转的数据与检索流水线:文档如何进入系统,如何被切分、标注、索引、召回、重排、生成,以及后续如何更新,都需要在一开始就被设计进去。
这篇文章不是对现场内容的逐字记录,而是参加分享后的整理与思考。很多结论结合了我自己对企业知识库、RAGFlow、AnythingLLM、LLM Wiki 这类工具的理解;其中 LLM Wiki 更偏向我的延伸理解,不代表分享本身明确推荐了这个方向。
企业级 RAG 的重点,不只是“能问答”
个人知识库或 demo 级 RAG 最容易验证的是“能不能问出答案”。企业级 RAG 则要多回答几个问题:
- 文档来源是否可靠,权限和版本是否清楚?
- 回答是否能追溯到原文、章节、文件和更新时间?
- 知识库更新后,旧答案是否会失效,索引是否会同步更新?
- 中文问题、英文术语、混合语言文档之间能否稳定召回?
- 不同业务场景是否需要不同的切分、检索、重排和模型策略?
如果这些问题没有被系统性处理,RAG 很容易停在“初看效果不错”的阶段。一旦文档数量增加、版本变化、权限复杂、术语混杂,系统就会暴露出召回不稳、答案过期、来源不清和维护成本高的问题。
分层架构:不要把所有问题都交给一个模型
企业级 RAG 更适合按层拆开,而不是把所有能力都塞进同一个 prompt 或同一个模型调用里。一个相对清晰的结构通常包括:
- 数据源层:文件、网页、知识库、内部系统、数据库、工单、会议纪要等;不同业务线可以进入不同数据库或数据域,而不是默认汇入一个统一知识库。
- 解析与清洗层:抽取正文、保留标题层级、表格、图片说明、代码块、页码和目录结构。
- 切分与索引字段层:把内容切成合适的 chunk,并把文件路径、章节、更新时间、版本号、hash、稳定记录 ID、外键、权限标签等结构化信息同步到索引侧。
- 索引层:向量索引、关键词索引、结构化字段索引,以及可能的混合检索。
- 召回与重排层:先尽量召回候选内容,再用 reranker、规则或业务约束筛掉噪声。
- 生成层:基于证据组织答案,附带引用,并在证据不足时明确说明。
- 评估与运维层:记录问题、召回命中、答案质量、用户反馈和知识库更新状态。
这种分层的好处是,每一层都可以选择更合适的工具和模型。解析文档时,可能需要更强的版面理解;生成答案时,需要更稳定的长上下文和中文表达;做重排时,也许一个专门的 rerank 模型比通用大模型更合适。企业级系统的关键不是“全部用最强模型”,而是把成本、延迟、准确率和可维护性放到同一个工程框架里权衡。
成本也要分层:GraphRAG 不应默认开启
分享里有一个对我很有提醒意义的测算示例:同一批材料中,GraphRAG extraction 约 $28.38,Global Index 约 $11.36,而 embedding/parse 约 $0.026,GraphRAG 与普通 embedding 路径的量级差距约 1092x。这里的具体金额受模型价格、数据规模、实现方式和时间变化影响,不能当成长期固定结论;但它说明了一个方向:GraphRAG 的主要成本并不在 embedding,而在 LLM indexing、graph extraction 和全局索引构建。
这意味着 GraphRAG 不适合作为企业知识库的默认开关。它更适合全库概览、跨文档关系图谱、主题聚类、实体关系探索这类问题;对于普通事实查询、命令查询、单案例召回,收益可能并不匹配成本。更稳妥的做法是把 GraphRAG 当成高成本增强层:先用普通向量、关键词和 metadata 过滤解决大多数问题,再把真正需要跨文档关系理解的场景单独路由过去。
按层选工具:AnythingLLM、RAGFlow 和 LLM Wiki 的位置不同
不同工具适合解决不同层的问题。AnythingLLM 更像一个适合快速搭建和使用的知识库问答入口,适合把本地文档、团队资料和模型能力串起来,快速形成可用的交互界面。它的价值在于低门槛、易部署、易试验。
RAGFlow 更强调文档解析、切分、知识入库和检索流程,尤其适合认真处理企业文档中的结构、表格、章节和增量更新。对企业知识库来说,文档进入系统前后的处理质量,往往决定了后面问答质量的上限。
LLM Wiki 则可以从知识组织和知识浏览的角度理解。很多企业知识并不只需要“问答”,还需要目录、主题、页面、关系和长期维护。把 wiki 式组织方式和 RAG 结合起来,可以让知识既能被人浏览,也能被模型召回。这是我基于分享内容进一步延伸出来的理解,不是把 LLM Wiki 写成现场明确给出的标准方案。
所以,选型不应该只问“哪个工具最好”,而要问“我现在卡在哪一层”。如果主要问题是让团队先用起来,AnythingLLM 可能更合适;如果主要问题是复杂文档入库和检索质量,RAGFlow 更值得投入;如果主要问题是知识长期组织和协作维护,wiki 类结构就不能忽略。
metadata:索引侧的追踪信息,不是业务主数据
metadata 经常被低估,但这里需要先划清边界:它是索引侧携带结构化信息的一种方式,不应该成为业务规则、产品归属或权限范围的主数据源。一个 chunk 不能只是“某段文本”,它还应该知道自己来自哪里、对应哪条数据库记录或哪个文件、哪个章节、哪个版本、什么时候更新、是否已经被新版本替代。
索引侧最基础的 metadata 或过滤字段至少包括:
- 数据库记录 ID、文件 ID、外键、文件路径或来源 URL
- 文档标题、章节标题和目录层级
- 创建时间、更新时间、版本号和同步批次
- 内容 hash、chunk hash 和 chunk ID
- 页码、段落位置、表格位置等定位信息
- 业务域 ID、产品线 ID、语言字段、权限标签等来自上游系统的索引副本
企业 RAG 不应假设所有内容都会进入一个统一知识库或统一向量库。根据不同业务线,内容可以进入不同数据库或数据域,每个数据库或数据域也会有自己的权限边界。业务域、产品线、权限范围等信息应该由数据库、业务系统和身份权限系统管理,RAG 入库时可以把稳定 ID、外键、产品线 ID、业务域 ID、权限标签等同步成索引过滤字段或 metadata 副本。尤其是权限范围,不能只靠一段文本 metadata 管理,而应该由数据库或身份权限系统控制,并在检索前或检索中完成过滤。语言可以作为文档属性或索引过滤字段,但语言识别、查询改写和双语召回策略也应该由数据源和检索链路共同管理。
更准确的检索流程应该是:先根据用户身份、业务线和数据库权限,决定这个用户可以访问哪些数据源、数据库、数据域或索引;再在这些被授权的范围内做向量召回、关键词召回和重排。metadata 或索引字段只能承载过滤键,或者承载数据库与权限系统返回的授权结果,不应该反过来成为权限和业务域的主数据来源。
这些索引侧信息不仅用于展示引用来源,也会影响检索过滤、增量更新、过期内容清理和问题排查。没有这些结构化信息的知识库,短期看起来也能回答问题,但长期会变成一堆无法追踪来源和版本的文本片段。
召回调参:top_n、reranker 和阈值不能分开看
召回问题经常被误判成生成模型问题。比如默认 top_n=6 时,目标 chunk 可能根本没有进入候选池。此时即使 reranker 很强,也只能在已经召回的 6 个候选里重排,不能把 embedding 阶段漏掉的内容凭空找回来。对复杂企业文档来说,把 top_n 提高到约 30,再交给 reranker 或规则层筛选,往往比直接抱怨模型“不会答”更有效。
启用 reranker 后,阈值也要重新校准,不能沿用 embedding-only 的相似度阈值。cross-encoder reranker 的分数尺度可能明显偏低,分享中出现过约 0.05 还能留下有效候选的示例,但这个数值不能机械照搬。正确做法是拿一组真实问题做标注,看目标 chunk 在 reranker 分数上的分布,再确定阈值、top_n 和是否需要 metadata 过滤。
增量更新:让知识库保持可维护
企业文档不是一次性导入后就不变了。制度会更新,产品文档会改版,API 会废弃,流程会调整。如果每次更新都全量重建索引,成本高、速度慢,也容易影响线上使用。因此,增量更新是企业级 RAG 的核心能力之一。
增量更新依赖稳定的结构化信息。没有数据库记录、文件 ID、路径、更新时间、版本号、目录结构、内容 hash、chunk ID 等信息,就很难判断哪些 chunk 需要更新、哪些旧内容应失效、哪些索引需要重建。metadata 是索引侧携带这些结构化信息的一种方式,但不是业务主数据本身。
以 RAGFlow 为例,它有增量更新相关能力,但实际效果仍然取决于上游文件标识、数据库记录、解析结果、chunk 标识和索引侧 metadata 是否稳定。如果每次导入都像一批全新的无名文本,系统就很难知道“这是原来那份文档的更新版本”,也很难只替换变化的部分。
比较理想的流程是:入库时保留稳定记录 ID、文件 ID、路径、目录层级、更新时间、版本号和 hash;再次同步时先比较文件级或段落级变化;只对变化内容重新解析、切分、embedding 和索引;对被删除或被替换的 chunk 标记失效;最后保留更新日志,方便排查某次问答为什么发生变化。
摄取稳定性:并发、限流和格式路由同样重要
企业 RAG 的入库阶段不只是“上传文件”。关键词生成、hypothetical questions、KG steps 等步骤可能会按 chunk 调用 LLM,高并发时很容易触发 rate limit 或 503。分享里有一个很实用的经验:把 concurrent tasks 从 15 降到 3,把 thread-pool 从 128 降到 12,整体反而更容易稳定跑完。对企业知识库来说,稳定完成一次摄取,通常比理论吞吐数字更重要。
文档格式也应该路由处理。PPT 可以先转成 PDF,再走 DeepDOC、OCR 或 vision 路径,以便保留版面和图文信息;Word 文档可以直接 ingest;旧的 .doc 文件则建议先转成 .docx,减少解析兼容性问题。格式路由做得越清楚,后面的 chunk、metadata 和引用定位就越可靠。
双语召回:中文问题和英文知识之间的桥
企业资料经常是中英文混合的:中文制度里有英文产品名,英文技术文档里有中文团队习惯叫法,用户提问时还可能使用缩写、别名或内部术语。如果只依赖单一路径的向量召回,很容易漏掉关键内容。
双语召回可以从几方面入手:
- 保留原文,不要为了统一语言而丢失术语细节。
- 建立术语表,维护产品名、缩写、中文译名、英文原名和内部别名。
- 查询改写时同时生成中文、英文或中英混合查询。
- 检索阶段结合向量召回、关键词召回、语言字段过滤和其他索引侧 metadata 过滤。
- 重排阶段让模型理解“术语相同但语言不同”的候选内容。
这里还有一个容易忽略的风险:BGE-M3 这类多语模型虽然适合中文和混合场景,但在 cross_languages 或 CN+EN 同时召回时,仍可能偏向同语言匹配。纯中文 query 有时会把英文 CLI 命令、英文参数名或英文原文挤出候选池。解决办法不是只相信“多语 embedding”,而是结合术语表、关键词召回、dense+sparse 混合召回,以及必要时的查询改写。
术语表在这里非常关键。它不是为了让文章更规范,而是为了让系统知道“同一个东西在不同语境里叫什么”。例如同一个内部系统可能有中文名、英文名、缩写和项目代号,如果不维护这些映射,用户换一种问法就可能召回不到正确内容。
向量库和 embedding 选型:先看运维边界
向量库选型也要回到实际边界。Qdrant 的检索性能和向量能力更突出,适合把向量检索作为独立基础设施认真运维;pgvector 的优势是运维简单,可以直接放在已有 PostgreSQL 体系里,适合团队先把链路跑通。两者不是绝对优劣,而是性能、复杂度、团队经验和现有数据库体系之间的权衡。
embedding 模型上,BGE-M3 对中文、英文和混合语言场景都比较友好,dense+sparse 组合也能增强关键词、命令、型号、参数这类精确匹配内容的召回。企业知识库里很多答案不是语义很相似就够了,具体命令、字段名、阈值和错误码经常需要更强的关键词路径托底。
回答质量来自工程闭环
RAG 的输出质量不只取决于最后一步的大模型。很多时候,答案错误是因为前面某一层已经出问题:文档解析漏掉了表格,chunk 切分破坏了上下文,索引侧没有携带稳定版本信息,检索只召回了相似但过期的内容,或者双语术语没有对齐。
不同任务的信任边界也不一样。事实检索、图片召回、metadata filtering 相对更可信,因为它们更接近“找证据”;跨案例归纳、数字阈值总结、穷举“找出所有 X”则要更谨慎,因为它们更容易被召回不全、样本偏差或模型归纳能力影响。尤其是穷举类问题,更适合走 index retrieval aggregation,而不是只把几个 chunk 塞给生成模型。
因此,企业级 RAG 需要评估和运维闭环。至少要能观察:用户问了什么,系统召回了哪些 chunk,重排后保留了哪些证据,答案引用了哪些来源,用户是否继续追问或反馈错误。只有这些记录足够清楚,团队才知道应该改 prompt、改切分、补术语表、调检索策略,还是更新原始知识文档。
我的结论
这次分享给我的最大提醒是:企业级 RAG 不是一个“接入模型”的项目,而是一个知识工程项目。模型很重要,但文档治理、数据库与业务系统中的主数据、索引侧 metadata、召回重排、增量更新、双语召回和评估闭环同样重要。
如果从零开始做企业知识库,我会优先把系统拆成几层:先保证文档入库质量,明确不同业务线、数据库、数据域、权限系统和索引侧 metadata 的边界,再选择合适的检索和重排策略,最后再优化生成效果。工具上可以用 AnythingLLM 快速搭建入口,用 RAGFlow 深入处理文档和检索流程,也可以结合 LLM Wiki 这类知识组织方式,让知识既适合人维护,也适合模型调用。
企业 RAG 的优化优先级,更多在输入侧工程,而不是只换一个更强的生成模型。解析质量、召回策略、top_n、reranker 阈值、缓存、metadata、格式路由、摄取稳定性和索引聚合,都会直接决定模型最后能看到什么证据。真正能长期工作的 RAG 系统,靠的不是一次漂亮的问答演示,而是每次文档变化、每次术语调整、每次问题失败之后,系统都能被定位、修正和继续演进。