1. 为什么我最终从"拼接式RAG"换成了 WeKnora 这种一站式方案
说个真实场景:我手头维护的资料库大概有三百多份文档,包括产品白皮书、售前方案PPT、扫描版合同、客户FAQ、以及大量带表格和图片的PDF。原本的检索方式就是网盘加文件夹,再配一个全文搜索工具,真到了"去年给某客户报的报价是什么"这种问题,翻十几分钟是常态。
最初我并没有直接上 WeKnora,而是走了很多人都会走的路:自己拼一套RAG。向量库用 Milvus,Embedding 用 BGE,LLM 打算先接云端 API,文档解析用 PyMuPDF 配合自研规则做切片。折腾了两周,能跑通,但效果一言难尽——表格被切得粉碎,扫描件直接是空文本,图片里的关键信息一个都抽不出来,问出来的答案驴唇不对马嘴。后来在一个开源社区的讨论帖里看到 WeKnora,才知道腾讯微信团队开源了这个项目。它的定位和普通RAG框架不太一样:它不是让你自己拼装,而是把数据接入、文档理解、切片、索引、混合检索、重排、生成、Agent 编排全部串成一条完整流水线,而且对中文场景的处理明显更细致。
我把它部署到本地之后,第一个感觉是"这才是文档该有的待遇"。PAW 文档理解流水线能把版面分析、OCR、表格转 Markdown、图表信息提取这些脏活全部接管,这在以前是我要写几千行代码去做的事。
这套系统适合谁来用?我觉得大概是两类人:一类是像我一样,被各种格式混乱、扫描件居多、表格密布的文档折磨得够呛,想搭一个真正能问问题的内部知识库;另一类是团队已经有一些 LLM 使用经验,但发现通用 RAG 框架对复杂文档的解析和召回精度不够,需要一个更完整的开源知识库底座。整篇文章我会把选型理由、模型决策、部署步骤、踩坑过程、调优方法完整记录下来,按我实际操作顺序写,不是照着官方 README 念,后者很多关键弯路根本不会告诉你。
先给一个结论:如果你现在的痛点只是"缺一个工作流编排平台",那 Dify 可能更合适;但如果痛点在于"文档根本进不去、检索不准、表格一塌糊涂",WeKnora 这种把文档解析做到极致的开源知识库方案,会更能解决问题。
2. 部署前的关键决策:模型放哪、机器要多大、选哪家Embedding
2.1 LLM 选型:我用 Ollama 跑 Qwen,而不是直接接云端 API
标题既然叫"本地部署实录",那大模型也应该是本地的,否则没意义。我最早考虑过直接把 WeKnora 的 LLM 接口指向 OpenAI 兼容的云端 API,这样最省事,但数据都要出内网,在办公场景里过不了安全这一关。所以最后选了 Ollama 作为本地模型运行时。
Ollama 的好处是极简:一条命令拉模型,一条命令起服务,而且它提供了 OpenAI 兼容接口,WeKnora 配置模型时可以直接走 OpenAI 兼容协议,非常方便。
模型选择上,我对比了三个方向:
- Qwen2.5-7B-Instruct:中文理解能力扎实,7B 量级在 CPU 上也能勉强跑起来,是我最终的主力模型。
- DeepSeek-R1-Distill-Qwen-7B:推理能力强,但速度偏慢,适合做"逐步推理"类的复杂问题。热词里也有 deepseek 本地部署,说明这条路很多人走通了。
- Qwen2.5-14B:如果你有 16GB 以上显存,强烈建议直接上 14B,答案质量比 7B 高一个档次,尤其是长文档总结场景。
量化级别我选的 Q4_K_M。7B 的 Q4_K_M 模型文件大概 4.7GB,14B 大概 9GB,这是 CPU 推理和显存占用之间的平衡点。再低比如 Q2 就别用了,质量衰减肉眼可见。
2.2 Embedding 和 Rerank 不能省,这是检索精度的真正分水岭
很多教程只教你配置 LLM,Embedding 随便选一个,Rerank 干脆不配。我在实操中的结论是:Rerank 对回答质量的影响甚至大于换一个大模型。
Embedding 我用的是 BAAI 的 bge-m3,原因很直接:它对中文语义的支持明显好于 nomic-embed-text 这类英文为主的模型,而且支持 8192 token 的长文本,处理整段方案描述不容易被截断。在 Ollama 里拉下来就是一条命令的事。
Rerank 也是 BGE 家族的 bge-reranker-v2-m3。它做的事情是:先让向量检索和关键词检索各召回一批候选文档,比如总共 50 条,Rerank 再逐条计算和问题的真实相关性,把最相关的 5 到 10 条排到最前面。这一步可以理解为"粗筛靠向量,精排靠重排"。如果你硬件紧张,可以先用一小批数据测试,确认检索精度成为瓶颈了再补上 Rerank,这个优先级是对的。
2.3 硬件底线:我的实测配置与建议
我部署用的是一台旧工作站,放在办公网里:4 核 8 线程 CPU,32GB 内存,没有 GPU。这个配置跑 Qwen2.5-7B 的 CPU 推理,单轮问答大概 3 到 6 秒,能忍,但并发一多就明显吃力。文档解析特别是 OCR 阶段非常吃 CPU,批量导入 PDF 时整个系统会卡顿。
给几个可以参考的档位:
| 部署规模 | 内存 | CPU/GPU | 模型 | 覆盖场景 |
|---|---|---|---|---|
| 尝鲜验证 | 16GB | 4核CPU | 7B Q4量化 | 单用户,少量文档 |
| 小型团队 | 32GB | 8核CPU或入门GPU | 7B~14B | 5~10人使用 |
| 生产环境 | 64GB | 24GB显存GPU | 14B+ | 多并发,大量文档 |
一个容易被忽略的点:内存不只是给 LLM 用的。文档解析进程、Embedding 模型、向量索引、Rerank 都会常驻内存,我实测纯 7B 模型 + bge-m3 嵌入 + bge-reranker,加上 WeKnora 前后端,内存占用轻松到 14GB。16GB 的机器跑全套真的很紧张,建议至少 32GB。
3. 从克隆代码到首次启动:环境准备、依赖安装和常见版本坑
3.1 环境准备:Python 版本是第一个坑
WeKnora 的部署方式在仓库 README 里有明确说明,但版本更新比较频繁,一些细节会变。我按当时实际操作的流程记录,你部署时如果发现命令不一致,以你拉取到的分支 README 为准。
先准备基础环境。我踩的第一个坑就是 Python 版本:必须用 3.10 或 3.11,太老或太新的版本在装依赖时都可能出编译错误。我一开始用的是系统自带的 Python 3.9,安装 requirements 里的某些依赖直接报错,换到 3.10 虚拟环境就正常了。
sudo apt install python3.10-venv python3.10 -m venv weknora-venv source weknora-venv/bin/activate前端部分需要 Node.js 和 pnpm,我用的是 Node 18。WeKnora 的前端是 Vue3 技术栈,直接用 pnpm 管理依赖。
3.2 后端依赖:PaddleOCR 是最大的定时炸弹
克隆代码后,进入项目目录安装后端依赖:
git clone https://github.com/Tencent/WeKnora.git cd WeKnora pip install -r requirements.txt这个命令表面上普普通通,但里面的雷在 PaddleOCR 相关依赖上。我第一次装的时候直接用默认命令,pip 给我装了一堆依赖,跑起来才发现 Paddle 的版本和 Python 不兼容,进程直接崩掉。
正确的姿势是:先单独装 CPU 版 PaddlePaddle,再装 PaddleOCR,装完之后再用 requirements 装其余部分。顺序搞反了就很容易踩到 Paddle 把 numpy 依赖锁上的坑。
pip install paddlepaddle # CPU版本,别默认装GPU版,否则CUDA依赖会卡死你 pip install paddleocr如果你的文档全是文本型 PDF,不需要 OCR,可以在 WeKnora 的解析配置里把 OCR 模块关掉,能省不少 CPU 占用。这个后面会再提。
前端构建:
pnpm install pnpm build第一次构建会拉不少依赖,耐心等就好。这个环节倒没遇到太诡异的坑,最多是网络问题导致个别包下载超时,重试即可。
3.3 配置与启动:把默认端口和数据库搞清楚
WeKnora 的配置文件主要在项目目录下的 config 相关文件里,里面涉及数据库地址、服务端口、日志路径等。默认配置可以走 SQLite,小规模验证足够;如果团队一起用,建议换成 MySQL,不然并发写入了会锁库。
启动方式我按官方命令来:后端是一个 Python 服务,前端是一个静态站点。开发模式下前端用 dev server 跑,生产环境用 build 后的静态文件让后端托管或者单独用 Nginx 代理。
首次启动后,浏览器访问前端地址,它会引导初始化管理员账号。到这里,还没接入模型,系统能打开,但问不了问题,因为还没配 LLM。
这里有一个值得强调的细节:系统默认监听地址如果是 127.0.0.1,只有本机能访问;如果想让局域网同事用,启动时要把 host 改为 0.0.0.0。但是不要把这个服务直接暴露到公网,这个我们在最后一章再展开说。
4. 接通本地模型:让问答系统真正开口说话
4.1 管理后台配置 LLM 接口
WeKnora 启动后,进入管理后台找到模型供应商配置页面。这里支持多种 provider,本地部署场景下最常用的是 OpenAI 兼容接口或者 Ollama 直连(取决于版本选项)。
我当时的配置是这样的:
- base_url 填
http://127.0.0.1:11434/v1 - api_key 填任意值,比如
ollama,因为本地 Ollama 不校验 key - model 名称填
qwen2.5:7b-instruct,注意必须是 Ollama 里 pull 下来的确切名称,多一个冒号少一个 tag 都会报错
Embedding 模型同理:把模型类型切到 embedding,base_url 指到 Ollama 的地址,模型名填bge-m3。Rerank 如果配了,也是同样的思路。
4.2 连通性测试:先 curl 后页面,别一上来就怪系统
配置完成后,WebUI 里通常有测试按钮。如果提示连接失败,不要急着怀疑是 WeKnora 的问题,先在本机用 curl 验证 Ollama 接口是否正常:
curl -X POST http://127.0.0.1:11434/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{"model":"qwen2.5:7b-instruct","messages":[{"role":"user","content":"你好"}]}'能正常返回内容,说明 Ollama 没问题,问题出在 WeKnora 侧的地址或者网络。这里有个非常经典的坑:如果你用 Docker 方式跑 WeKnora,容器里的 127.0.0.1 指向的是容器自己,不是宿主机。这时候要把 base_url 改成http://host.docker.internal:11434/v1,Linux 下如果用 docker compose,可以加extra_hosts: - "host.docker.internal:host-gateway"。我在这一步卡了快一个小时。
另一个容易踩的是 CORS。浏览器直接访问前端页面发起跨域请求时,Ollama 默认对来源有限制。解决办法是给 Ollama 设置环境变量:
OLLAMA_ORIGINS='*' ollama serve简单粗暴,但本地内网环境这么干问题不大。要注意的是这个环境变量是进程级的,设置完要重启 ollama 服务。
4.3 第一次真实问答:预期管理很重要
模型配好之后,我先建了一个很小的知识库,放了一份 Markdown 格式的 FAQ,文档内容是"XX 系统如何开通、常见错误码含义"。导入成功后,做索引,然后提问:"客户反馈登录一直失败,错误码 10023,怎么处理?"
效果比我预期的好:系统能准确引用 FAQ 里的对应条目,并且返回了处理建议,答案下面还挂了引用来源。但同时我也发现了第一个问题:7B 模型对问题的理解过于字面化,如果问题里不包含错误码,它就不太会联想到相关 FAQ。这说明检索链路本身该做的活已经做完了,瓶颈开始转向模型推理能力。
所以我建议第一次测试时把预期调低一点:不要指望 7B 模型在没有 Rerank、没有调优的情况下就给出惊艳答案。第一步只确认链路通、引用准,后面再逐步优化。
5. 文档解析和 Agentic RAG 的真实体验:PAW 到底强在哪
5.1 把一份扫描版方案 PDF 扔给 PAW 之后的对比
为了测试 WeKnora 的文档理解能力,我专门找了一份旧方案文档:一个扫描版的 PDF,大概是十几页,里面包含彩色封面、目录、带财务数据的表格、几张架构图、还有一些手写批注的痕迹。
我将它导入 WeKnora,后台任务跑了一阵子,打开解析结果一看,确实有点东西:文字内容被完整 OCR 出来了,表格被还原成了 Markdown 表格格式,架构图里的文字说明也被单独提取成了图片注释,多栏排版的阅读顺序没有被搞乱。这些都是之前我用开源工具自研解析时会崩溃的典型场景。
再用对照组来验证:同一份 PDF 用 PyMuPDF 直接抽文本,结果是一些空行和偶尔乱码,因为整个文件本质是图片;用单纯的开源 OCR 工具跑,文字是出来了,但表格结构完全丢了,多栏文字串成了一坨。PAW 的价值在于流水线式地把版面分析、OCR、表格结构识别、阅读顺序还原串起来,而不是单点工具能比的事。
5.2 混合检索和 Rerank 在生产中的真实分工
WeKnora 的检索不是单一向量召回,而是混合了语义向量、关键词命中、知识图谱关联。这一点在业务文档里非常有用。
举个例子,文档里经常出现"CRM-2024-01"这种产品编号。你拿向量去搜"CRM-2024-01",效果通常不稳定,因为向量模型对这个字符串的理解很弱,但关键词检索能精准命中。反过来,"客户关系管理系统的升级方案"这种语义描述,关键词搜不到,向量能轻松召回到相关段落。混合检索就是让这两条路各自发挥优势,再合并结果。
Rerank 在最终的排序阶段把关。之前我把上下文数量设得很大,一次性送三十条检索结果给模型,结果上下文爆炸,回答质量急剧下降。加上 Rerank 之后,先把候选压缩到 top 5,模型输入更干净,回答质量直接提升。所以我在调优时把 Rerank 的优先级放在很前面。
5.3 Agentic RAG 的实际效果:什么时候该用,什么时候别滥用
WeKnora 的 Agentic RAG 模式在管理后台可以开启。它的逻辑是让模型不再做"一次检索一次回答",而是先拆解用户的复杂问题,再决定去哪个知识库检索、调用什么工具、分几步回答。
我测试过一个多步骤问题:"对比新老两版售后服务政策中,退换货时效的变化,并总结对客户沟通的影响。"基础 RAG 模式下,模型很容易只找到其中一个版本就开答,漏掉对比。切到 Agent 模式后,它会先拆成"找到两个版本-抽取退换货条款-对比差异-生成结论"几步,看起来更接近人的检索路径。
但我也要泼一盆冷水:Agent 模式不是默认开启就万事大吉的。如果知识库范围太大、工具权限没有收敛,模型反而会"自由发挥",检索一些无关的内容,甚至凭空生成中间结论。我的做法是在配置里把 Agent 可访问的知识库范围明确限定,并给每个知识库加上清晰的角色描述。别让它自由发挥太多。
6. 踩坑实录:从部署到稳定运行的完整排查链路
6.1 症状一:模型服务连接超时,排查到最后是 localhost 指向问题
现象:页面测试连接提示 LLM 服务连接超时。这是部署最常遇到的第一个大坑。
排查链路:
- 先在宿主机执行
curl http://127.0.0.1:11434/v1,确认 Ollama 服务确实在跑。 - 再确认 WeKnora 的 base_url 是否正确。如果 WeKnora 跑在 Docker 容器里,
127.0.0.1指容器自己,必须改用host.docker.internal。 - 检查 Ollama 是否开启了跨域限制。前端直连时会报 CORS 错误,设置
OLLAMA_ORIGINS='*'后重启。
最后定位到的根因其实就是第二点:容器内外 localhost 的含义不同。这个坑在本地部署里极具代表性,属于"写配置时看起来完全正确,跑起来就是不通"的典型。
6.2 症状二:文档索引成功,但答案答非所问
现象:知识库索引任务显示成功,提问后答案和文档内容没有明确关系,甚至引用来源都不对。
排查链路:
- 先打开文档解析结果,确认文本内容是否真的被正确提取。结果发现文本在,但被切成片段。
- 再检查检索调试页面,看输入问题后到底召回了哪些片段。发现召回的段落里只有一半和问题相关,另一半是其他主题的内容。
- 进一步查了 chunk 设置,默认的切分大小偏大,一段话里混了两个主题,向量检索时语义就不够聚焦。
解决方案是重建索引并把切片策略调小。比如 chunk_size 从默认值调成 512,上下文重叠 100。具体要结合文档特点调,但方向是让每个切片尽量聚焦单一主题。改完后重新导入或重建索引,答案质量明显好转。
这个过程让我意识到一个经常被忽视的事情:RAG 系统的错误不一定出在模型,很多是先出在文档切片环节。切片像切菜,切得太大,一锅炖不下;切得太碎,味道就散了。WeKnora 虽然切片策略可配置,但默认值未必适合你的文档。
6.3 症状三:7B 模型回答读不出重点,开头啰嗦、结尾敷衍
现象:Qwen2.5-7B 在长文档问答时,答案前半段在复述文档标题,后半段直接说"请参考文档第X页",没有实际内容。
排查链路:
- 检查送进模型的上下文内容,发现一次塞了太多检索片段,超出了模型的 32K 上下文窗口,被系统自动截断。
- 截断后,模型只看到了文档开头的章节信息,没看到真正的内容段落。
- 量化模型本身对长文本的归纳能力有限,7B 在上下文很长时容易"只看见开头和结尾"。
解决方案有两步:第一步是我的老办法,启用 Rerank 后把召回数量从 10 降到 5,让上下文更精炼;第二步是把 max_new_tokens 调大一些,给模型更多输出空间。条件允许的情况下换 14B 模型会彻底改善这类问题。
6.4 症状四:导入文档时解析任务失败,日志指向 PaddleOCR
现象:批量导入 PDF 时,部分任务失败,日志里有 Paddle 相关的异常。
排查链路:
- 确认是 GPU 版 Paddle 在没有 CUDA 环境时的兼容问题,卸载后安装 CPU 版解决。
- 部分扫描版 PDF 存在旋转页,需要开启 OCR 中的自动旋转校正选项。
- 对于双栏排版的扫描件,版面分析尤其重要。如果不开版面分析,两栏文字会被按行串联,上下文语义错乱。
最终建议是:如果你的文档以扫描件为主,先单独跑一轮 OCR 测试任务,确认 Paddle 环境没问题再批量导入。批量导入前用小样本试跑,能省下不少排查任务失败的时间。
7. 部署完之后的日常使用与进阶方向
7.1 我的日常操作流:从"搭好"到"用好"
系统稳定运行之后,我把日常操作固定成了一套流程。新增文档统一放到一个"待处理"目录,定期上传到 WeKnora 并触发解析;每周跑一轮事先准备的问题测试集——大概二十个常见客户问题,逐个问答,看答案质量有没有波动;如果换了模型版本,先用这套测试集做 A/B 对比,不会直接在生产知识库上开新模型。
另外一个容易被忽略的事是索引维护。文档更新后,旧索引里的内容不会自动消失,需要重新导入或删除。我的做法是给每个知识库设定负责人,文档版本更新时同步做索引重建。不然旧版本和新版本的内容混在检索结果里,答案可能引用已经作废的政策或报价。
7.2 团队权限与 SSO:OIDC 和账号体系
WeKnora 支持多用户体系,而且热词里也有"weknora oidc"这个检索词,说明不少人在问 SSO 集成的问题。我在内网环境里配置了 OIDC 对接企业现有的统一认证,这样团队成员不需要单独注册账号,直接用公司账号登录。这一块在团队场景里几乎是必须的,否则每个人都要手动开账号,权限也不好收敛。
权限控制的粒度上,我的建议是:业务敏感的知识库要有独立的访问权限控制,不要让所有登录用户都能看全量文档。我们实际就把"财务相关规则库"和"销售产品库"分开了,不同角色只能检索自己有权限的知识库。
7.3 结合 Dify 做更复杂的工作流编排
部署完一段时间后,我也尝试了把 WeKnora 和 Dify 结合。思路是:WeKnora 负责文档解析、知识库管理和精准检索,Dify 负责更灵活的对话工作流、外部工具接入、以及和现有业务系统对接。比如"客户问题进来自动分类-不同分类走不同知识库-再触发工单创建"这类流程,Dify 的编排体验比 WeKnora 内置功能更细腻。两个开源项目各司其职,反而是比较舒服的组合方式。
7.4 进阶功能:GraphRAG 和模型微调
如果知识库里的实体关系很复杂,比如供应链关系、组织架构、人员变动这类数据,可以考虑开启 WeKnora 的图增强能力,也就是 GraphRAG 方向。它会把文档中的实体和关系抽出来构建知识图谱,检索时不光找相似段落,还能沿着关系链找答案。我实测在"公司上下游关联"这类问题上,图谱增强明显比纯向量检索强。
模型微调这块我没有深入,但客观说必要性不大。对大多数团队,换更好的基础模型、调好切片和检索参数,收益远大于微调。微调是针对模型"回答风格"或"特定领域术语"做定制时才需要考虑的选项。
整套系统跑了快两个月,最直观的感受是:开源知识库的差距不在模型,而在文档解析和检索链路的成熟度。WeKnora 让我把精力从"怎么洗文档、怎么搭索引"这类脏活里解放出来,集中到真正的调优和场景设计上。如果你手里也有一堆无法直接喂给大模型的文档,我建议直接拿 WeKnora 跑一轮最小知识库验证,先把链路通起来,再逐步加 Rerank、Agent 和 Dify 工作流。后面我还打算把企业微信里的历史消息自动同步进去,到时候再更新一篇实践记录。