1. 从“知识割裂”说起:WeKnora 到底想解决什么问题
如果你最近在折腾 RAG(检索增强生成),大概率会有一种很拧巴的感觉:文档丢进去了,向量库也建了,问一个简单问题它答得还行,但一旦问题稍微复杂一点——比如“我们去年Q3那次架构调整之后,订单模块的负责人是谁,他当时定的那个方案后来改过几版”——模型就开始胡言乱语,要么答非所问,要么把几个不相干的片段硬拼在一起。
这不是你的提示词写得不好,而是传统 RAG 的底层逻辑有硬伤。它把文档切成一块块互不相干的碎片,检索的时候只看“哪块碎片和问题最像”,完全不管碎片之间的逻辑关系。结果就是知识割裂:答案明明散落在三四个文档里,但系统只捞回来一两个,剩下的全靠模型脑补。
WeKnora 是腾讯微信团队开源的一个知识库项目,它想干的事情,就是把这堆碎片重新“缝”起来。它不是一个单纯的向量检索工具,而是一套带Agent 编排能力的 RAG 框架——你可以把它理解成一个“会自己规划检索路径”的知识库。普通 RAG 是“你问一句,它查一次”,WeKnora 是“你问一句,它先想想要查哪几个地方、按什么顺序查、查完怎么拼”,这个“想”的过程,就是 Agent 在起作用。
这篇文章适合三类人看:一是正在做企业知识库、被 RAG 召回率折磨的开发者;二是想搞清楚 Agentic RAG 和普通 RAG 到底差在哪的技术负责人;三是想在本机把 WeKnora 跑起来、但被部署文档绕晕的实操派。我会把原理、部署、踩坑、调优这几件事拆开讲,尽量让你看完就能动手。
2. WeKnora 的架构骨架:Agent 编排 + 沙箱执行 + 多路检索
2.1 为什么普通 RAG 会“卡在瓶颈上”
先说清楚 RAG 的瓶颈到底在哪。传统 RAG 的流程是固定的:用户提问 → 向量化 → 向量库相似度检索 → Top-K 片段塞进上下文 → LLM 生成。这条链路的问题在于,检索是一次性的、无反馈的。如果第一次检索没捞到关键信息,后面就没有补救机会了。
我实测过一个场景:问“某项目的验收标准里,关于并发压测的那条是怎么写的”。文档里其实有两处提到,一处是验收章节,一处是测试方案附录。普通 RAG 只召回了验收章节那段,但那段写的是“参照测试方案执行”,真正的数值在附录里。模型拿到一个“参照执行”的片段,只能编一个数值出来。
WeKnora 的思路是引入Agent 循环:检索完之后,Agent 会判断“这些信息够不够回答问题”,不够就换个查询词再检一次,或者去查别的数据源。这个“判断—再检索”的过程可以迭代多轮,直到信息足够或者达到轮次上限。这就是热词里说的agentic rag——RAG 不再是单次管道,而是一个有决策能力的智能体。
2.2 沙箱在 WeKnora 里扮演什么角色
热词里“沙箱”出现频率很高,很多人第一反应是支付宝沙箱支付,但在 WeKnora 语境下,沙箱指的是Agent 执行代码或工具调用的隔离环境。
为什么需要沙箱?因为 Agent 在编排过程中,可能需要动态执行一些操作,比如解析一个表格文件、调用一个计算函数、跑一段数据清洗脚本。这些操作如果直接在宿主机上跑,风险很大——万一模型生成的代码有问题,可能把系统文件删了。沙箱就是给这些操作划一块“安全操场”,跑挂了也只影响沙箱内部。
WeKnora 的沙箱机制我理解下来,核心是两点:一是资源隔离,限制 CPU、内存、执行时间;二是权限隔离,沙箱内的代码只能访问被授权的数据,碰不到宿主机的敏感目录。这个设计在企业场景里很关键,因为企业知识库往往连着内部系统,不能让 Agent 随便乱来。
2.3 多路检索:向量、关键词、图谱怎么配合
WeKnora 不是只靠向量检索。它支持多路召回,包括:
| 检索方式 | 擅长场景 | 短板 |
|---|---|---|
| 向量检索 | 语义相似、口语化提问 | 对精确术语、编号不敏感 |
| 关键词检索 | 精确匹配、代码、编号 | 无法理解同义表达 |
| 图谱/本体检索 | 实体关系、多跳推理 | 构建成本高 |
热词里提到的ontology rag和graphrag,说的就是图谱这条路。比如你问“A 项目的负责人同时负责哪几个其他项目”,向量检索很难直接答,因为它需要“A 项目 → 负责人 → 该负责人的其他项目”这样两跳关系。图谱检索就是干这个的。
WeKnora 的做法是把这几路结果做融合排序,再交给 Agent 判断。这个融合不是简单加权,而是根据问题类型动态调整权重——事实型问题偏关键词,推理型问题偏图谱,开放型问题偏向量的语义匹配。
3. 本机部署 WeKnora:从零到能问出第一句话
3.1 部署前的环境盘点,别急着敲命令
很多人一上来就 clone 仓库、跑 docker compose,结果卡在依赖上。我建议先花十分钟把环境盘清楚。
WeKnora 的部署方式主要有两种:Docker Compose 一键起,或者手动分组件部署。对绝大多数人来说,Docker Compose 是首选,因为它把向量库、后端服务、前端、模型接入这些组件的依赖关系都处理好了。
你需要准备的东西:
- Docker 和 Docker Compose:版本别太老,Compose 建议 v2 以上,v1 的语法在新版镜像里可能报错。
- 至少 16GB 内存:如果本地还要跑 embedding 模型,32GB 更稳。我试过 8GB 的机器,光向量库和 backend 就把内存吃满了,模型加载直接 OOM。
- 磁盘空间:镜像加上模型文件,预留 50GB 比较保险。embedding 模型和 rerank 模型加起来可能就十几个 G。
- 模型接入方式:你可以用在线 API,也可以本地跑 Ollama。热词里“ollama + 简易本地 rag 知识库”说的就是这个路子。本地跑的好处是数据不出内网,坏处是慢,而且吃显存。
提示:如果你只是想把流程跑通、看看效果,先用在线 API 接入,别一上来就折腾本地模型。等流程通了,再换本地模型做数据隔离。
3.2 Docker Compose 起服务的完整步骤
假设你已经装好了 Docker,下面是实操流程。
第一步,拿到项目代码。从官方仓库 clone 下来,进入目录。目录结构里一般会有docker-compose.yml或者deploy文件夹,先看一眼 README 里有没有额外的环境变量说明。
第二步,配置环境变量。这是最容易出问题的地方。通常需要配这几类:
# 模型相关 LLM_API_KEY=你的key LLM_BASE_URL=模型服务地址 EMBEDDING_MODEL=嵌入模型名称 # 数据库相关 POSTGRES_PASSWORD=自定义密码 VECTOR_DB_TYPE=向量库类型 # 服务端口 BACKEND_PORT=8080 FRONTEND_PORT=3000这里有个坑:环境变量的命名在不同版本里可能不一样。我遇到过.env.example里写的是OPENAI_API_KEY,但代码里读的是LLM_API_KEY,结果服务起来了但模型调不通。解决办法是去代码里搜一下os.getenv或者process.env,确认实际读取的变量名。
第三步,起服务。
docker compose up -d加-d是后台运行。起来之后用docker compose ps看各容器状态,重点看 backend 和向量库是不是 healthy。如果某个容器一直 restart,用docker compose logs 容器名看日志。
第四步,初始化。首次启动通常需要建库、建表、初始化管理员账号。有些版本会自动跑 migration,有些需要手动执行初始化脚本。看日志里有没有 “migration completed” 之类的提示。
第五步,访问前端。默认一般是http://localhost:3000,用初始化时设的账号登录,然后创建一个知识库,上传一个测试文档,问一句话试试。
3.3 部署阶段最容易踩的五个坑
我把部署时踩过的坑列一下,你对照着排查能省不少时间。
坑一:端口冲突。3000 和 8080 是最容易被占用的端口,起服务前先lsof -i:3000看一眼。如果被占,改 compose 文件里的端口映射。
坑二:向量库连不上。向量库容器起来了,但 backend 报连接超时。多半是网络配置问题——compose 里各服务要在同一个 network 下,且 backend 连向量库要用服务名而不是 localhost。
坑三:模型调用 401。环境变量配了但没生效,或者 key 有空格。检查.env文件里有没有多余的空格和引号,Docker 读环境变量对格式很敏感。
坑四:embedding 维度不匹配。你换了一个 embedding 模型,但向量库里的 collection 是按旧模型维度建的,插入数据时报维度错误。解决办法是重建 collection,或者换回原维度模型。
坑五:内存不足导致容器被杀。日志里出现Killed或者 exit code 137,基本就是 OOM。减少并发、换小模型,或者加内存。
4. 把文档喂进去:解析、切分与知识图谱构建
4.1 文档解析:PDF、Word、图片各有什么坑
WeKnora 支持多种文档格式,但不同格式的解析质量差别很大。
PDF 是最麻烦的。扫描版 PDF 需要 OCR,文字版 PDF 如果排版复杂(多栏、表格、公式),解析出来经常是乱的。我实测下来,带表格的 PDF 解析后表格结构基本丢失,变成一堆错位的文字。如果你的知识库里有大量表格类文档,建议先转成 Markdown 或者结构化格式再喂进去。
Word 文档相对好一些,但要注意样式。如果文档里用了大量文本框、艺术字,解析也可能出问题。
图片这块,热词里有人问“rag 知识库能存储图片嘛”。答案是能存,但检索逻辑不一样。图片通常需要先做多模态 embedding,或者用 OCR 提取文字后再走文本检索。WeKnora 对图片的支持程度取决于你接入的模型能力——如果 embedding 模型支持多模态,图片可以直接向量化;如果不支持,就得先 OCR。
提示:文档解析质量直接决定 RAG 的上限。与其在检索阶段调参,不如在入库前把文档洗干净。这一步偷懒,后面全是坑。
4.2 切分策略:为什么固定长度切分是灾难
文档切分是 RAG 里最被低估的环节。很多人直接用默认的“按 512 token 切”,结果切出来的片段要么语义不完整,要么把关键信息切断了。
WeKnora 支持更细的切分策略,我建议按文档结构来切:
- 按标题层级切:一级标题下的内容作为一个大块,二级标题下作为子块。这样每个块都有明确的主题。
- 按语义切:用模型判断句子之间的语义连贯性,在语义转折处切分。
- 重叠切分:相邻块之间保留一定重叠(比如 10%),避免关键信息正好落在切分点上被切断。
我踩过一个坑:一份技术方案文档,关键结论写在章节末尾,结果固定长度切分正好把结论和它前面的论据切开了。检索时只召回论据,模型不知道结论是什么,答出来的东西完全跑偏。后来改成按标题切分,问题就解决了。
4.3 知识图谱构建:让实体关系不再割裂
这是 WeKnora 区别于普通 RAG 的核心能力之一。它在文档入库时,会尝试抽取实体和关系,构建一个轻量级的知识图谱。
比如文档里写“张三负责订单模块,李四负责支付模块,订单模块依赖支付模块”,图谱会抽出三个实体(张三、订单模块、支付模块)和两条关系(负责、依赖)。当你问“订单模块出问题会影响谁”时,图谱可以沿着“依赖”关系找到支付模块,再找到李四。
构建图谱的代价是入库变慢,而且抽取质量依赖模型能力。我的经验是:实体密集、关系复杂的文档值得建图谱;纯叙述性、关系松散的文档建了也没多大用。你可以按知识库类型决定是否开启。
5. 检索调优:命中率上不去的排查链路
5.1 先定位是召回问题还是生成问题
RAG 答不好,先别急着调模型。第一步是判断问题出在“没召回”还是“召回了但没答对”。
方法很简单:把检索到的片段打印出来看。如果片段里根本没有答案,那是召回问题;如果片段里有答案但模型没答对,那是生成问题。
WeKnora 的调试面板里一般能看到每次查询的检索结果和 Agent 的决策过程。如果没有面板,就在日志里加打印。这一步不做,后面所有调优都是瞎猜。
5.2 召回率低的四种典型原因
原因一:查询词和文档用词不一致。用户问“怎么配置”,文档里写的是“设置方法”。向量检索能缓解这个问题,但如果 embedding 模型对领域术语不敏感,还是会漏。解决办法是加同义词表,或者用查询改写——让模型先把用户问题改写成几个不同表述,分别检索。
原因二:Top-K 太小。默认 Top-K 可能是 3 或 5,对于复杂问题不够。可以调到 10 甚至 20,然后用 rerank 模型精排。热词里的rag hit rate说的就是这个指标。
原因三:切分粒度不对。块太大,噪声多;块太小,信息不全。这个只能靠试,没有万能参数。
原因四:多路检索权重失衡。如果关键词检索权重太低,精确术语就召不回来;如果图谱权重太高,开放问题又会被过度结构化。WeKnora 允许调这些权重,建议按知识库内容特点来配。
5.3 Rerank 模型:召回之后的第二道筛子
召回阶段追求“不漏”,rerank 阶段追求“精准”。WeKnora 支持接入 rerank 模型,对召回的片段做二次排序。
rerank 的原理是 cross-encoder:把问题和每个片段拼在一起送进模型,直接输出相关性分数。它比向量相似度准得多,但慢得多。所以典型流程是:向量检索召回 50 条 → rerank 精排出前 5 条 → 送给 LLM。
我实测下来,加了 rerank 之后命中率能提升 20% 到 30%,尤其是那种“答案藏在长文档中间”的场景。代价是每次查询多几百毫秒延迟。如果你的场景对延迟不敏感,强烈建议开。
6. Agent 编排与并发:从能用走向好用
6.1 Agent 循环的轮次控制与死循环防范
Agent 会自己决定“再检一次”,但如果不加限制,它可能陷入死循环——检了没找到,换个词再检,还没找到,再换……最后把 token 烧光了也没答出来。
WeKnora 里一般有最大轮次配置。我的建议是设 3 到 5 轮。超过 5 轮还没找到,基本说明知识库里确实没有,再检也是浪费。同时要设一个“无进展检测”:如果连续两轮召回结果高度重合,就强制停止。
6.2 并发场景下 Agent 扛不扛得住
热词里有人问“ai agent 怎么扛并发”。这是个真问题。Agent 编排比普通 RAG 重得多——一次查询可能触发多轮检索、多次模型调用,资源消耗是普通 RAG 的好几倍。
WeKnora 的并发能力取决于几个瓶颈:
- 模型服务的并发上限:在线 API 一般有 QPS 限制,本地模型看显存。
- 向量库的查询并发:Milvus、Qdrant 这类向量库并发能力不错,但配置不当也会成瓶颈。
- 沙箱的资源池:如果 Agent 频繁执行代码,沙箱的创建和销毁开销不小,需要做池化。
实操建议:先压测单次查询的耗时和资源占用,再算单机能扛多少并发。别一上来就追求高并发,先把单次查询的质量做稳。
6.3 和 Dify、RAGFlow 的定位差异
热词里“dify ragflow weknora 开源版 企业功能比较”是个高频问题。我简单说下我的理解:
- Dify更偏应用编排平台,RAG 只是它的一块能力,强项是可视化工作流。
- RAGFlow强在文档解析,尤其是复杂 PDF 的深度解析,切分质量高。
- WeKnora的差异点在 Agent 编排和沙箱执行,更适合需要多步推理、动态工具调用的场景。
选哪个不是非此即彼,很多团队是组合用的——用 RAGFlow 做文档预处理,用 WeKnora 做检索和 Agent 编排。
7. 一些实操心得和后续可扩展的方向
部署和调优过程中,我最大的体会是:RAG 的效果上限在数据准备阶段就决定了。文档解析、切分、图谱构建这三步做扎实,后面检索调优是锦上添花;这三步偷懒,后面怎么调都是事倍功半。
另外,Agent 编排虽然强大,但别滥用。简单的事实型问答,普通 RAG 就够了,上 Agent 反而增加延迟和不确定性。只有当问题需要多跳推理、多数据源融合、动态工具调用时,Agent 的价值才体现出来。
后续可以扩展的方向,我个人比较关注两个:一是OIDC 接入,把知识库权限和企业统一身份认证打通,这样不同部门的人只能看到自己有权限的文档;二是和 Obsidian 这类本地笔记工具的联动,热词里“weknora 和 obsidian”有人问,思路是把 Obsidian 的 Markdown 库直接作为知识源同步进去,这样个人笔记也能被 RAG 检索到。
最后分享一个小技巧:调检索参数时,固定一组测试问题,每次改完参数都跑一遍,记录命中率。别凭感觉调,感觉最不靠谱。我一开始就是凭感觉调 Top-K,调了半天发现还不如默认值。后来建了个 20 条问题的测试集,每次改动都有数据支撑,效率高多了。