☰
RAG+Wiki:打造高效团队知识库的完整实战指南
2026/10/2 10:37:37 网站建设 项目流程

我最近又把团队的知识库翻出来折腾了一遍。之前大家辛辛苦苦整理的 Wiki,使用率一直上不去:文档写了不少,但真到找答案的时候,要么翻半天目录,要么关键词搜出来一堆不相关的内容。直到我把 Wiki 接进 RAG 流程之后,情况才明显改观——问答案这种事交给检索增强生成,而 Wiki 继续负责沉淀知识,两者各干各擅长的事,知识库才终于“活”了过来。

如果你也在维护个人笔记、团队 Wiki、产品手册这类东西,并且困惑“为什么写了没人看、搜了找不到”,这篇内容应该对你有用。我会拆解 RAG 的核心链路,聊聊 Wiki 侧该怎么配合建设,再给一套零基础可复制的本地实操方案,最后把大家最容易踩的坑和排查经验整理成表格。无论你是运维、研发,还是做知识管理的运营同学,都能按图索骥。

1. 为什么是“RAG 找答案,Wiki 长知识”

1.1 两件工具各管一段:检索器与知识库的定位差异

RAG 和 Wiki 并不是同类工具,而是知识体系里两个不同层级的组件。Wiki 解决的是“知识怎么组织和沉淀”:它有目录、有分类、有双链、有全文,目标是把信息变成可以被人类理解和持续维护的结构化资产。RAG 解决的是“知识怎么被调用”:给定一个问题,它先从知识库里检索出候选片段,再让大模型基于这些片段生成答案,目标是把知识准确地送到提问者面前。

这个分工特别重要,因为直接拿 LLM 当知识库用,或者拿 Wiki 全文搜索当问答用,都是走了弯路。LLM 本身学过很多通用知识,但对你团队内部的具体流程、某个系统的 Token 配置、某条历史决策的来龙去脉,它根本没有记忆。RAG 相当于给大模型装了一个“外部大脑”,回答时把相关文档临时喂给它,这就把“模型记忆”和“组织记忆”剥离开了。而 Wiki 恰恰是那个最值得喂给 RAG 的“组织记忆”——它有结构、有上下文、有版本痕迹,天然比一堆散落的聊天记录和邮件更适合作为知识源。

我见过不少团队跳过 Wiki 直接把聊天记录、工单内容丢进向量库,结果问答群里确实能出答案,但答案质量很飘,因为聊天记录里的上下文太碎了,谁说的、什么时候说的、后来有没有推翻,这些信息都丢掉了。Wiki 虽然写作成本高一点,但对答案可追溯性要求高的场景,这笔前期投入完全值得。

1.2 传统知识库为什么总是“建而不用”

很多知识库项目的真实状态是:内容在积累,使用率却在滑坡。用户打开 Wiki 首页,看到十几个栏目,每个栏目下面又有几十篇文档,光是确定“该不该看这篇”就要花掉不少时间。全文搜索在某些场景下好用,但遇到问句语义匹配就非常吃力——比如系统告警时你想查“怎么处理内存占用过高”,传统搜索可能只匹配到“内存占用”字面相关的页面,却漏掉一篇标题叫“服务降级演练预案”的实操文档。

Wiki 的另一个问题是“人找文档”的路径成本。阅读者得先猜问题归属于哪个栏目,再顺着导航一级一级点进去,这种前置心智负担会劝退大多数忙碌的同事。大家最终会流向即时沟通工具,直接在群里问,得到的答案又变成新的聊天信息流失掉,形成一个“越不用越找不到、越找不到越不用”的恶性循环。

RAG 恰好把“找”这个过程从用户身上接管了。提问者不需要知道答案藏在哪篇文档里,他只需要把问题问出来,系统负责检索、排序、引用原文。这看似只是交互方式变了,实际上是知识库从“被动查阅”走向“主动供给”。对我个人而言,最大的变化是:写完一篇新文档不再焦虑有没有人看,因为 RAG 会把它推到恰好需要它的人面前。

1.3 这套组合到底适合谁来用

先给一个简单的判断标准:如果你手里的知识文档数量超过两百篇,或者内容更新频率较高,或者问答结果需要溯源到原始出处,那么“Wiki + RAG”这套组合基本就是当前成本收益比最理想的方案。

适合的场景大致有三类。第一类是团队内部知识库,包括研发文档、SOP、故障复盘、产品需求等,用户是同事,答案必须可靠且有出处。第二类是个人知识管理,典型如 Obsidian 里的笔记体系,个人笔记往往跨度大、主题杂,RAG 能有效避免“记了但想不起在哪”的问题。第三类是产品帮助中心或客服知识库,用户问的问题相对固定,但对答复规范性和响应速度要求很高,用 RAG 可以大幅节省人工翻文档的时间。

不适合的场景也要说清楚:如果你的知识库总共就二三十篇文档,传统搜索已经够用,上 RAG 反而增加维护成本;如果你的问答内容全是实时数据,比如库存、订单状态,那不是 RAG 的主场,应该去做数据库查询;如果你需要的是闲聊或开放写作,而不是“基于已有知识回答”,也没必要上这套方案。工具嘛,合适比热闹重要。

2. RAG 链路逐个拆:从文档到答案的完整流程

2.1 接入与解析:别让格式吃掉信息

RAG 的第一步不是向量化,而是把 Wiki 里的内容变成干净的纯文本。这一步看起来不起眼,但恰恰是后续所有环节的根基,我在实际项目里吃过不少亏。

Wiki 内容常见的形态有 Markdown、富文本、PDF、表格、图片等。Markdown 和纯文本最好处理,直接解析即可;但飞书文档、Confluence、语雀这类平台导出的 HTML 或 PDF,里面充满了样式标签、页眉页脚、分页符,如果直接把脏文本送进切片器,你会得到大量包含“目录”“第 N 页”“仅供内部使用”这种噪声的片段,检索命中率会肉眼可见地下降。

我的建议是:在导出一份文档后,先做一轮清洗,至少包含这几件事——去掉重复页眉页脚、把表格转成 Markdown 表格或键值对文本、统一代码块的缩进、把图片用 OCR 转成文字并保留位置信息。这些操作不复杂,但能避免大量无效 embedding 占用向量库空间。如果你用的是飞书 Wiki,导出 markdown 后再用脚本清理一遍是最省心的路径;如果是 Confluence,可以走它的空间导出接口拿 HTML,再转纯文本。

提示:清洗阶段要保留文档的标题层级。切片时把标题拼进每个片段的内容里,检索时就能更好地利用文档结构信息,这个细节后面还会展开。

2.2 切片与向量化:决定命中率的基础

文本清洗干净之后,就要面对 RAG 里最核心的工程问题:怎么切片、用什么模型做 embedding。

切片的目标是让每个文本片段语义相对完整、长度适中。片切太短,比如一两句话,检索时可能抓到细碎信息但缺乏上下文,生成阶段容易产生错误理解;片切太长,比如一整篇文档塞进一个向量,检索精度又会下降,而且超过模型上下文窗口还会被截断。我常用的起点是 chunk_size 设在 500 到 800 个 token 之间,chunk_overlap 设 50 到 100 个 token,然后根据检索效果再调整。overlap 的作用是让相邻切片之间保留一部分重复内容,避免某个句子被拦腰截断在两个切片里导致语义断层,这个类比就像把一本书拆页时,页与页之间故意重叠复印一小部分,保证翻页时不丢字。

切片策略也不是只有“固定长度”一种。更精细的做法是按 Markdown 标题层级切分,例如把每个二级标题下的内容单独作为一个切片;如果某个小节还是太长,再按段落进一步细分。LangChain 里的 MarkdownHeaderTextSplitter 可以用来做这件事,效果大部分时候优于纯字符数切分。还有一种思路是语义切分,按句子向量之间的相似度自动判断哪里是语义边界,对小标题缺失的文本很有效,但计算成本略高。

embedding 模型的选择直接决定了检索质量的上限。目前中文场景我实测下来,BGE-M3 是个综合表现不错的起点,它对中文、英文和跨语言的语义理解都比较稳,Ollama 里可以直接拉取;如果预算和资源充足,也可以尝试 GTE-Qwen2 这类更强的模型。向量维度不需要自己操心,embedding 模型会输出固定维度向量,BGE-M3 是 1024 维,Nomic-Embed-Text 是 768 维,向量库会自己适配。

2.3 混合检索与重排:把“跑偏”拉回来

纯向量检索一个常见的尴尬是:语义相关但字面不匹配的内容能召回,可有时候关键词完全匹配的内容反而被挤到后面。比如用户问“服务挂了怎么处理”,向量检索可能更偏好语义相近的“服务不可用应急预案”,而漏掉标题就叫“服务宕机处置步骤”的文档。解决这个问题,业界惯例是“混合检索”——把向量检索和关键词检索(BM25)的结果做融合,再去重、排序。

具体落地不需要你自己写搜索引擎。LlamaIndex 里有 QueryFusionRetriever,LangChain 里也有 EnsembleRetriever,可以把向量召回和 BM25 召回的文档列表合并后重新排序。我这边常用的是简单的加权融合:每路检索各取 top 20,把命中同一个片段的分数相加,最后统一排序取前 5。这个做法不像 RRF(Reciprocal Rank Fusion)那么讲究,但胜在简单直观,调起来快。

重排环节同样值得做。等候选片段进到最终 Prompt 之前,加一个 reranker 模型(比如 BGE-Reranker-V2-M3)对候选片段重新打分,能显著提升答案质量。原因在于 embedding 检索阶段只做了粗粒度匹配,而 reranker 基于完整的交叉编码器对“问题-文本片段”做细粒度相关度打分,精度高一个档次。代价是会比向量检索慢一点,但对离线知识库场景完全可接受。如果检索结果里经常出现“看着相关但答非所问”的情况,八成就是跳过了重排这一步。

2.4 生成与引用:答案要有据可查

RAG 的最后一步是让 LLM 基于检索到的片段生成答案。这一步我踩过最深的坑是:把一堆原文片段拼进 Prompt 后直接问“请回答”,模型往往回答得很流畅,但夹带了不少它自己脑补出来的内容,尤其当检索片段质量不高时,它甚至会强行“圆场”。

我的做法是给模型定非常明确的规矩。Prompt 里会写明:你只能根据“资料”部分的内容作答,无法回答时直接说“知识库中没有找到相关答案”,不要编造;回答时尽量带上原文片段里的关键信息,并附上对应文档标题作为引用。temperature 通常设低一点,0.1 到 0.3 之间,减少随机性。生成之后,有必要的话再补一道“答案溯源校验”——把模型生成的每个关键论断回查一遍原始片段里是否存在,这在小规模测试里很管用,可以防住大部分幻觉。

还要注意上下文窗口。检索到的候选片段通常取 top 3 到 top 5,但每个片段长度各不相同,如果直接全部拼进去,很可能超出模型的上下文限制。我习惯在拼接前先按重排分数裁剪出一个 max_context_characters 上限,比如 4000 个字符,超出就截断。这样既能保证 Prompt 不被撑爆,也倒逼检索环节必须真的找到最核心的内容,而不是靠“多喂一点”来碰运气。

3. Wiki 侧建设:怎么让知识“长”起来

3.1 知识拓扑:MOC、双链与命名空间

RAG 只是“取知识”的手段,知识本身的质量和结构还得靠 Wiki 来保证。如果 Wiki 本身就是一篇篇孤立的文档、标题随意、逻辑混乱,那 RAG 检索到的片段也会相应地混乱。所以 Wiki 侧的建设重点不是“多写”,而是“写得有结构”。

我个人非常推荐在 Wiki 里维护 MOC(Map of Content,内容地图)机制。MOC 本质上是一篇“索引型页面”,它不像普通文档那样详细解释内容,而是把某一类主题下的相关文档以列表、表格或卡片的形式聚合起来,相当于给知识库画了一张导航图。比如“数据库运维 MOC”下面可以列出备份策略、慢查询治理、主从切换、故障演练等条目。这么做对 RAG 的直接好处是:当用户问一个范围较大的问题时,检索系统有机会先命中 MOC,再通过 MOC 的关系把相关子文档一并关联出来。

双链(双向链接)也是让知识“长”起来的重要机制。Obsidian 里的[[笔记名]]、飞书知识库里的“相关内容”引用,本质上都在给文档之间建立显式关联。这些关联数据能帮你做两件事:一是人工点击浏览时可以顺藤摸瓜;二是可以导出成知识图谱,为后续升级到 GraphRAG 或本体 RAG 提供关系基础。内容多起来之后,光靠平面目录管理会越来越吃力,关系网络才是对抗知识碎片的武器。

命名空间和命名规范同样不能省。我见过太多知识库里有“新建文档 3”“未命名 7”这种名字,检索时模型就算找到了,也不知道这是篇什么鬼。建议从一开始就定死规则:每篇文档的标题必须是名词短语,能概括本页主题;按“主题/子主题/文档名”建立目录层级;同一主题下的文档只保留一份权威版本,其他页面通过链接指向它,而不是复制粘贴。

3.2 三类团队的知识沉淀方案

不同规模的团队,Wiki 建设方案差别很大。我给三类团队各给一套可执行的起步方案,你可以对号入座。

个人场景最简单,本地用 Obsidian 就够。Obsidian 的仓库本身就是一堆 Markdown 文件,文件夹结构即命名空间,双链和 MOC 都在原生支持范围内。把这堆 md 文件作为 RAG 的数据源没有任何障碍,目录加载、切片、向量化一条龙跑通。我自己的笔记库就是这么干的,检索时直接复用同一套 RAG 管道,维护成本几乎为零。

中小团队的推荐方案是用飞书 Wiki 或语雀这类一体化协作平台。好处是多人编辑和权限管理是现成的,手机上也能查阅。落地时要注意导出的便利性:飞书文档支持导出 Markdown,语雀也支持批量导出,这些导出文件可以当作 RAG 的同步源。如果你不想手动导出,也可以写个定时脚本调用文档导出接口,把导出的文件同步到向量库。

大型团队或对数据安全很敏感的团队,我建议考虑自建 Wiki 系统,Confluence 和 Outline 是两种经常被我拿来对比的选项。Confluence 功能全、生态成熟,但较重,页面层级多了以后管理成本很高;Outline 更轻量,基于 Markdown,且 API 很友好,适合做 RAG 数据源。选哪套不重要,重要的是想清楚一个问题:你的知识源是否方便定期、自动地导出成结构化文本?这一点直接决定了后面 RAG 管道的数据新鲜度。

3.3 让 Wiki 成为 RAG 的知识源

Wiki 和 RAG 结合得越自然,效果越好。一个常见的反面例子是:团队在 Wiki 里写了大量“临时性内容”,比如某次活动的通知、某天的会议纪要,这类信息时效性强、价值低,被 RAG 检索到时反而会干扰答案。建议 Wiki 里明确划分“长期知识区”和“临时工作区”,RAG 只索引长期知识区,或者通过元数据(比如文档标签)过滤掉低价值内容。

版本管理同样要重视。知识是会过时的,某篇 SOP 在 5 月更新过流程,如果 RAG 库里还存着 3 月的旧版本,模型就可能把过时步骤当成正确答案。解决方案有两层:第一层是 Wiki 侧保留版本历史和更新时间字段;第二层是同步管道里记录文档的 Hash 值,内容变化了才重新切片和写入向量库,这样既省计算资源,也避免旧版本残留。

我实际用的同步策略是:每个 Wiki 文档导出的 md 文件头部保留id和updated_at元数据,同步脚本比对本地缓存里的updated_at,只更新有变化的文档;被删除的文档在向量库里也要同步删除,否则用户会搜到一堆已经不存在的页面。这个机制配合 Wiki 的版本历史,基本能满足知识库日常更新的需求。

4. 零基础可复制的本地 RAG 实操

4.1 环境准备与模型选择

实践出真知,光看理论不动手,RAG 的很多坑你永远发现不了。这里给一套可以在本地电脑上跑通的方案,依赖极简、无需付费。

先说模型选择。本地推理我用 Ollama 作为模型运行时,它把模型管理和调用封装得比较舒服。LLM 我常用 qwen2.5:7b,中文能力在 7B 档位里表现扎实,回答也不会太啰嗦;如果你的机器配置一般,可以用 qwen2.5:3b 先跑通流程再换大模型。embedding 模型推荐 bge-m3,检索精度和中文支持都在线。重排模型也可以用 bge-reranker-v2-m3,但本地跑重排需要额外装依赖,初学阶段可以先跳过。

注意:embedding 模型和 LLM 是两回事,千万别只拉一个。缺少 embedding 模型时,向量化直接报错;缺少 LLM 时,检索环节正常但无法生成答案。这两个坑几乎是新手必踩。

项目侧我用 LangChain 来做管道编排,版本按 0.2.x 写,代码思路在更新版本里同样适用。你还需要安装几个 Python 包:langchain、langchain-community、chromadb、ollama。Chroma 是一个轻量级向量数据库,纯本地运行,适合起步阶段;等文档量上到几十万篇再考虑 Milvus 或 Qdrant 不迟。

4.2 用 LangChain 搭一个最小问答系统

我把这套最小系统的代码贴在下面,你照着跑就能出一个本地问答接口。前提是:本机已经装好 Ollama 并拉取模型;有一个./wiki目录,里面放着从你的 Wiki 导出的 Markdown 文件。

import os from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.embeddings import OllamaEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOllama from langchain.schema import HumanMessage # 1. 加载 Wiki 目录下所有 md 文档 loader = DirectoryLoader( "./wiki", glob="**/*.md", loader_cls=TextLoader, loader_kwargs={"encoding": "utf-8"}, ) docs = loader.load() # 2. 切片:每个片段 800 token,重叠 100 token splitter = RecursiveCharacterTextSplitter( chunk_size=800, chunk_overlap=100, ) chunks = splitter.split_documents(docs) # 3. 向量化并写入 Chroma embeddings = OllamaEmbeddings(model="bge-m3", base_url="http://localhost:11434") vectorstore = Chroma.from_documents( documents=chunks, embedding=embeddings, persist_directory="./chroma_db", ) # 4. 检索器:取相关度最高的 5 个片段 retriever = vectorstore.as_retriever(search_kwargs={"k": 5}) # 5. 生成回答 llm = ChatOllama(model="qwen2.5:7b", base_url="http://localhost:11434", temperature=0.2) def ask(question: str) -> str: retrieved = retriever.invoke(question) context = "\n\n".join( f"[文档标题:{d.metadata.get('source', '未知')}]\n{d.page_content}" for d in retrieved ) prompt = ( "你是一个知识库问答助手。请只根据下方提供的资料回答用户问题," "不要编造资料中不存在的内容;如果资料不足以回答问题,请直接说明。\n\n" f"资料:\n{context}\n\n问题:{question}" ) response = llm.invoke([HumanMessage(content=prompt)]) return response.content # 6. 测试一问 print(ask("我们的回滚流程是什么?"))

这段代码有几点值得说明。DirectoryLoader 会把文件路径写进metadata["source"],我把文档标题拼接进上下文里,这样模型回答时可以引用来源,后续做溯源也方便。切片器我选 RecursiveCharacterTextSplitter 而不是简单的字符分割,因为它是按换行、段落、句子逐级往下切的,对中文文本更友好,切出来的片段语义完整性更好。

4.3 检索效果测试与参数调优

系统能跑起来之后,就该关心检索质量了。你先准备一组“问题-期望答案所在文档”的测试集,大概 20 到 50 条,然后测两个关键指标:命中率(Hit Rate)和 MRR。命中率表示问题对应的文档是否出现在检索结果前 5 条中,MRR 会再衡量它排得多靠前。我习惯用下面这段代码做快速测试:

def hit_rate(retriever, questions, ground_truth_docs): hits = 0 for q, gold in zip(questions, ground_truth_docs): candidates = retriever.invoke(q) if any(gold in c.page_content or gold in c.metadata.get("source", "") for c in candidates): hits += 1 return hits / len(questions)

如果命中率低于 70%,优先调整三个方向:第一,把 chunk_size 调小一点,比如从 800 降到 500,观察命中率是否回升;第二,检查是不是 embedding 模型选得不够合适,可以先在测试集上对比不同模型的 top1 命中率;第三,加入 BM25 混合检索,很多时候纯向量检索对专有名词和缩写不敏感,混合后命中率能涨一截。另一个实用技巧是给切片拼接标题后重新 embedding,这样检索到某个切片时,它的“主题上下文”也在向量中,相关度排序更准。

调参不是一次性的事。我每次往 Wiki 里新增一批内容,都会重跑一次测试集,对比新旧命中率。如果新增内容把原有答案“挤掉”了,说明切片或去重逻辑有问题;如果整体命中率稳定,才说明知识库结构是健康的。这个习惯能帮你早早发现内容组织上的问题,而不是等到线上用户吐槽“答案不对”再去救火。

5. 常见问题与排查技巧实录

5.1 检索命中率低,怎么定位

命中率低的原因往往是“混合问题”,不能只调一个参数。我把排查路径按优先级排成一张速查表,你可以从上往下试:

现象可能原因优先排查方向
检索结果和问题明显不相关embedding 模型能力不足换 bge-m3 或 gte-qwen2,重新入库
相关文档能搜到但排在后面纯向量检索对专有名词不敏感加 BM25 混合检索,重排后取 top5
切片内容太碎,上下文缺失chunk_size 过小调大到 800 并增加 overlap
新文档搜不到,旧文档重复出现同步管道未做增量更新检查文档 Hash 和 updated_at 比对
同一主题多篇文档互相干扰Wiki 结构混乱合并重复文档,建立 MOC 做聚合入口

还有一个容易忽略的点:用户提问的语言和文档语言不一致。如果你 Wiki 里不少文档是中文,但用户拿英文缩写提问,embedding 模型跨语言能力不够时就会漏召回。bge-m3 对中英混合支持不错,但如果你的场景经常出现这种交叉,建议在预处理层做“同义词扩展”,比如把 “SOP” 和“标准作业流程”都映射成同一组关键词参与检索。

5.2 图片、PDF 扫描件怎么进知识库

“RAG 知识库能存图片吗”这个问题我经常被问到。直接回答:如果图片里的信息是文字型内容,OCR 后进知识库是完全可行的;如果是纯图形、图表这类视觉信息,传统文本 RAG 存不了,得走多模态路线,成本会明显上升。

最务实的路线还是 OCR。PDF 扫描件用 PaddleOCR 或 Tesseract 转成文本,图片里的流程图、架构图如果里面有文字,OCR 也能捞出一部分信息。转出来的文本最好保留原有章节结构,再走常规切片和向量化流程。表格类图片建议转成 Markdown 表格,这比 OCR 成一行文字再让模型“猜”要可靠得多。

如果预算和技术储备都比较充足,可以试试多模态 embedding 方案,例如 CLIP 系列模型可以把图片和文本映射到同一向量空间,用户文字提问时能直接检索到图片,再由多模态 LLM 看图回答。但这套方案对部署资源和推理延迟的要求都更高,现阶段更适合在特定的图片资料库场景里做,而不是所有 Wiki 内容一刀切。

5.3 增量更新与知识失真的处理

Wiki 是活的,内容经常变,RAG 管道不能每次全量重建。全量重建的坏处不只是慢——向量库重新写入大量向量时如果处理不当,旧数据残留会导致知识“新旧混杂”,答案就会失真。

我的做法是给文档建一个指纹库:每篇文档算一个 Hash,比如取 md5 或 sha256,存在一份本地状态文件里。同步脚本每轮先扫描所有文档,Hash 有变化的才重新切片和写入向量库,Hash 没变的直接跳过;检测到某篇文档已删除,就到向量库中按source元数据整篇删除对应向量。Chroma 支持按元数据过滤删除,这个操作用起来很方便。

知识失真的另一个来源是 Prompt 上下文冲突。如果检索到的 top 5 片段里既有旧版本又有新版本的信息,模型很可能选它“觉得合理”的一条,而不是选时效性最新的一条。简单粗暴的解法是:切片内容里带上文档的updated_at字段,并在 Prompt 里注明“多个来源冲突时,优先以更新日期最新的内容为准”。这个规则成本极低,但能显著减少新旧知识打架的情况。

5.4 从 RAG 到 GraphRAG、Agentic RAG 的演进路径

做熟了基础 RAG 之后,很多人会碰到下一个瓶颈:有些问题不能靠“检索一段文本”回答,而是要把分散在多个文档里的实体关系串联起来。比如问“我们系统里 A 服务依赖哪些模块、哪些模块又依赖数据库 X?”这种问题,纯向量检索很难直接命中,因为答案散落在不同段落,没有一个片段能完整描述整个依赖链。

这时候就该考虑 GraphRAG,也就是在向量检索之外加一层知识图谱。你可以从 Wiki 的双链关系、文档里的名词链接中抽取实体和关系,构建一张图。查询时先通过向量检索定位到核心实体,再沿着图结构往外扩展一跳、两跳,把相关的实体与关系一并拿回来。微软开源的 GraphRAG 项目和“本体 RAG”思路都是朝这个方向走的,差别在于一个从文档抽取实体,一个预先定义领域本体。对医疗、法务、工业等强领域知识的场景,本体 RAG 的可控性明显更好。

还有一条演进路径是 Agentic RAG,也就是把 RAG 从“一次检索一次回答”变成“多步推理、反复检索”。比如用户问一个复杂问题时,Agent 先判断需要哪几类资料,分步检索,每轮根据检索结果判断是否信息足够,不足就继续搜,甚至调用工具查数据库,最后再汇总答案。这种模式灵活很多,但调试成本也高,建议至少等基础 RAG 的命中率和答案质量稳定之后再尝试。就我个人经验而言,先把普通 RAG 做好做扎实,上述进阶方案才有意义,否则 Agent 每一步都在检索噪声数据,出来的结果只会更乱。

最后分享一点个人体会。我折腾这套“Wiki + RAG”组合最大的收获,不是问答准确率提升了多少,而是整个团队对知识库的态度发生了变化。以前写文档像交作业,写完就完事;现在大家知道文档会被检索、会被引用、会在有人提问时被自动调出来,写作时会更在意标题是否清晰、结构是否合理、内容是否更新。一套好的工具链,最终倒逼的其实是知识生产的习惯——RAG 负责找答案,Wiki 负责长知识,而让这两件事形成正向循环的,还是背后持续维护知识的人。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询