
前阵子帮团队搭内部问答系统选型时折腾了不少时间。Dify、FastGPT、RAGFlow 这几个主流开源项目我都测过一轮最后真正落地的是腾讯微信团队开源的 WeKnora。整套本地部署环境跑顺之后团队日常问报销流程、查代码规范、翻历史项目方案都直接在知识库问答里拿答案不用再靠翻群聊记录和共享文件夹过日子。这篇就是这次 WeKnora 本地部署的完整实录覆盖选型理由、硬件评估、docker-compose 部署链路、Ollama 本地大模型接入、知识库文档解析切分以及问答效果调优和一路踩过的坑。想在内网搭一套开源 AI 知识库问答系统的同学可以直接照着操作。1. 为什么是 WeKnora在开源知识库选型里它赢在哪1.1 团队的真实痛点与实际诉求我们团队的知识资产分布极其分散企业微信群里几十个文档、飞书知识空间里的项目记录、本地硬盘里的 Word 和 PDF、还有几个人脑子里才有的经验。平时找人问事情从你知道那个谁做的方案在哪到这个流程怎么走一来一回至少耽误半小时。所以当时立项时就两条硬指标一是所有数据必须放在内网不能上传第三方平台二是普通人能直接对话式获取答案不需要学检索语法。带着这个目标去看开源产品Dify 明显偏重 AI 应用编排知识库只是其中一个模块FastGPT 功能全面但部署和二次开发都比较重RAGFlow 的文档深度理解很出色但整个系统资源吃得比较猛。WeKnora 是腾讯微信团队开源的知识库问答系统后端 Go 编写前端 Vue检索核心基于 Elasticsearch定位非常纯粹文档进知识库用户问问题系统给答案。这种单点专注恰好契合我们的场景。1.2 技术架构和检索链路拆解WeKnora 让我比较满意的点是它没有把检索做得很玄乎而是走了工程上最稳的一条链路。文档上传后先落到 MinIO 对象存储解析出的文本进 MySQL 做元数据管理真正的检索在 Elasticsearch 里完成。检索时采用多路召回策略一部分走 BM25 关键词匹配一部分走向量语义检索最后通过 RRFReciprocal Rank Fusion把两路结果融合排序。这个思路和当前企业级 RAG 的主流做法一致没有为了炫技引入复杂组件运维负担相对可控。大模型对接层面WeKnora 支持 OpenAI 兼容接口、Ollama、Azure 等多家推理服务。这意味着我不需要被绑定在某一家的模型上本地用 Ollama 起一个大模型或者后面换成云端 API都只是改配置的事。1.3 和其他开源项目的取舍判断我把当时对比过的几个项目列一下方便同做选型的同学参考项目核心定位部署复杂度检索能力适用场景WeKnora知识库问答较低Go 单体多路召回 RRF 融合文档检索、企业内网知识问答DifyAI 应用编排中依赖配置复杂工作流、Agent 应用FastGPT知识库 流程中偏高基础 RAG需要强流程编排的场景RAGFlow深度文档理解偏高文档解析强复杂格式文档、精细切分我的判断是如果团队核心诉求就是文档进来、问答出去不做复杂的 Agent 工作流WeKnora 这种专注型产品的学习成本和维护成本都更低。微信团队的社区活跃度和文档质量也算加分项至少出了问题能找到人讨论。2. 本地部署前的准备硬件规格和五个必须搞定的中间件2.1 我用什么机器在跑先给参考基准。我部署用的是一台 8 核 16G 内存的服务器系统是 Ubuntu 22.04数据盘是 500G 的 SSD。这个配置跑 WeKnora 加一个 7B 参数的本地大模型完全没有问题如果是 14B 以上模型建议内存直接上到 32G显存不讨论因为纯 CPU 推理走的是内存。磁盘方面ES 索引、MinIO 对象存储和 MySQL 都会持续吃空间500G 是底线我跑了一个多月文档量到几万片时才用掉不到 100G所以起步 200G 也够。硬件的另一个关键是网络拓扑。WeKnora 需要单独部署Ollama 可以部署在同一台机器上也可以单独放一台 GPU 机器。两层之间只需要端口互通比如 Ollama 监听 11434 端口WeKnora 所在服务器能访问到这个端口即可。2.2 五个核心依赖各自的职责WeKnora 的部署不是单一二进制它依赖一套标准中间件。我在首次部署前用一张表理清了它们的角色Elasticsearch核心检索引擎同时承担文档索引、BM25 关键词检索、向量检索的存储和计算。这是整个系统最重的组件内存大头全在它身上。MySQL存放知识库元数据、用户信息、文档状态、问答日志。系统运行管理全靠它。Redis负责缓存、会话管理以及部分异步任务的消息队列缺了它系统跑不起来。MinIO对象存储所有上传的原始文档、解析出的文件内容都放这里S3 兼容协议。WeKnora 应用服务本身Go 后端提供 APIVue 前端提供界面通常会通过 Nginx 统一对外暴露。搞清楚这些组件的角色后续排错会轻松很多。比如上传的文档找不到了第一反应应该是去 MinIO 里确认对象是否存在而不是抓瞎。2.3 Docker Compose 编排 vs 逐组件手动装我强烈建议用 Docker Compose 方式部署。WeKnora 官方仓库提供了完整的 docker-compose 文件里头把 MySQL、Redis、MinIO、ES 和前后端服务都编排好了。第一次部署时我试过半手动方式在宿主机直接装 ES 和 MySQL结果环境变量不一致导致一堆连接问题后来还是回退到 Compose。用 Compose 的最大好处是中间件版本固定几个服务之间的网络通过自定义桥接网络天然互通不需要手工维护 HOSTS。唯一的例外是 Ollama它建议装在宿主机或者独立容器里单独管理因为模型下载和更新比较频繁混在业务编排里容易连带重启。如果必须在一个 Compose 里管理注意设置好健康检查和依赖顺序。3. 一步步跑通部署从拉取仓库到首次登录3.1 获取代码和准备环境变量部署第一步是拉取 WeKnora 官方仓库然后查看目录结构。稳定做法是先切到最新的 Release 标签而不是直接拉 master避免数据库表结构变动导致初始化脚本不匹配。代码拿到手后核心工作是配置部署环境变量。需要关注的关键项主要是两类一类是中间件连接信息MySQL 的库名账号密码、Redis 的地址端口、MinIO 的 AccessKey 和 SecretKey、ES 的地址另一类是系统对外配置比如前端回调地址、后端监听端口、文件上传大小限制。这些值在第一次启动前就要定好因为初始化脚本会按这些连接信息建库建表回头再改环境变量需要处理旧的初始化状态比较麻烦。3.2 启动弹性检索Elasticsearch 的初始化细节在整套中间件里Elasticsearch 是最容易出问题的。首次启动前必须确认宿主机内核参数允许的虚拟内存区域数量达到要求否则 ES 容器会启动几秒就退出。标准做法是执行参数调整命令把值改到 262144然后确认这个配置在服务器重启后仍然保留这一步不做好后面所有服务全白搭。ES 内存方面也需要单独处理。Compose 里默认按宿主机可用内存按比例分配堆内存但单一索引和检索场景下保守设置比较稳妥。我个人的经验是把 ES 的 JVM 堆大小固定到 2G 到 4G 这个区间。堆太小会导致查询频繁触发 GC堆太大会挤压宿主机内存Ollama 那边推理时就会因为内存不足而卡顿。ES 起来之后还需要确认中文分词插件已经生效。WeKnora 的索引设计默认依赖 IK 分词器来保证中文检索质量不装 IK 插件的话中文问句的召回结果会惨不忍睹。验证方式很简单进入容器执行分词的 REST API看输出是否包含 ik_smart 和 ik_max_word 分词器信息。3.3 启动 MySQL、Redis、MinIO 和 WeKnora 主服务中间件之间的启动顺序按依赖关系来MySQL 和 Redis 最快MinIO 需要先确认它的数据目录权限ES 最慢因为它要初始化分片和副本。我的经验是先单独启动这几个中间件等 MySQL 能连接、ES 健康状态变绿、MinIO 能通过浏览器登录控制台之后再启动 WeKnora 后端服务。首次启动时后端会执行初始化流程自动创建数据库表结构和基础配置。观察容器日志是最直接的方式看到类似的日志表示初始化完成。接着启动前端容器通过 Nginx 对外暴露。整条链路跑通后浏览器访问服务器 IP 加对应端口应该能看到登录页面。3.4 首次登录与账号安全处理默认安装完会有一个管理员账号这属于部署初始状态必须第一时间登录后台修改密码。这里要提醒一下默认密码是公开信息如果你部署的服务暴露在不可信网络不改密码等于把知识库大门敞开。即使全部在内网也强烈建议立即改掉并且用强密码。登录进去之后先别急着传文档我建议先做三件事第一确认系统设置里的存储地址确实指向 MinIO第二检查组件监控页面里 ES、MySQL、Redis 的连接状态是否全部正常第三把文件上传大小限制调到自己团队实际需要的值否则后面传大 PDF 会莫名其妙失败。这几步确认完部署阶段才算真正收尾。4. 大模型接入用 Ollama 把推理能力装进内网4.1 为什么我选 Ollama 而不是直接调云端 API大模型接入是问答系统能回答的关键。市面上很多团队图省事直接接云端 API但我们选了 Ollama 这条路核心原因是数据不出内网。知识库里所有文档内容都是内部资料把它们发给第三方模型厂商做语义理解在合规层面过不去。本地部署 Ollama 之后一切推理都发生在自己的服务器上隐私问题从根上解决。另一个现实原因是成本。团队内测试阶段调用频率不稳定按 API 调用次数计费其实很贵而且频繁调试的时候调一次错一次钱烧得心疼。本地部署的模型反正用自己的机器跑随便折腾。4.2 安装 Ollama 和选择合适的中文模型Ollama 的安装非常轻量下载对应平台的安装包或者直接用官方一键脚本装完注册成系统服务即可。这里要特别设置一个环境变量让 Ollama 监听所有网卡地址因为默认配置下它只监听回环地址WeKnora 所在机器在另一台服务器时根本连不上。设置完记得重启 Ollama 服务。模型选择上我先后试过两个7B 参数的 Qwen 2.5 和 DeepSeek-R1 系列。对于 16G 内存的机器7B 量化版比较合适单轮问答速度可以接受多轮对话时上下文稍长也不至于把内存吃爆。如果是 32G 机器可以上 14B 模型回答质量确实会明显上一个台阶。拉取模型后用一条命令验证 Ollama 本地接口能正常返回结果确认推理链路没问题再配置 WeKnora。4.3 在 WeKnora 后台完成模型服务配置进入 WeKnora 后台的模型服务配置页面新增一个推理服务。因为 Ollama 提供了 OpenAI 兼容的接口类型选择 OpenAI 兼容即可地址填 Ollama 部署机器的 IP 加端口再加 /v1 路径API Key 可以随便填入一个占位字符串因为 Ollama 本地默认不做鉴权。模型名称填之前拉取的具体模型名保存后执行一次测试请求。这个环节容易忽略的是 Embedding 模型的配置。RAG 系统里文档向量化依赖 Embedding 模型如果没配好文档解析后写入 ES 的向量就是空或者错误的。Ollama 的模型库里也有专用的向量模型常见的是 bge-m3效果还不错。我的建议是对话模型和 Embedding 模型分开配别图省事用同一个大模型来干向量的活效果和效率都不对。两者都配置好之后在知识库测试上传一个文档确认解析完成后有一条带向量信息的记录大模型接入才算真正打通。5. 知识库构建实战文档解析、切分和索引的底层逻辑5.1 支持的文件类型与解析链路WeKnora 支持上传的格式比较常规PDF、Word、Markdown、TXT、HTML 这些主流的都能处理。上传之后文件会被拆成存储层和解析层两步文件二进制落到 MinIO后台解析任务读取文件内容并提取文本。我实际用过一轮之后的感觉是Markdown 和 TXT 的解析最稳定Word 偶尔出现样式丢失PDF 在中文场景下问题最多后面踩坑章节细说。解析出的文本不会直接拿去索引而是先进入切分模块。切分任务做完每个文本块会调用前面配置的 Embedding 模型生成向量再把向量和原文一起写入 Elasticsearch。到这里知识库才具备了被检索的条件。整个过程是异步的文档上传后需要等一会儿才能在后台看到解析完成状态文件多的时候就别盯着页面等过几分钟再回来看。5.2 切分策略为什么直接决定检索效果这是整个知识库构建里最容易被低估的环节。我一开始图省事用默认切分参数跑了一批文档结果提问时经常答非所问。后来细看切分结果才发现默认策略把一些过长段落硬切成了两个逻辑上不相干的片段导致片段之间缺乏上下文语义关联。切分参数的调整原则是这样的文本块太小比如几百个字检索时单块信息量不够大模型拿不到完整上下文文本块太大比如几千个字向量检索时语义被稀释召回的片段不够精准。比较好的起点是每块控制在 500 到 1000 字之间并且相邻块之间保留少量重叠保证跨块断句的地方语义不丢。同时要开启按标题层级切分的选项让文档的结构信息参与切片这样检索结果更容易命中章节级别的上下文。5.3 多路召回和重排序机制的价值切分完成之后检索质量靠的是多路召回。用户输入一个问题WeKnora 会同时跑两路查询BM25 关键词匹配捕捉精确词汇向量检索捕捉语义相近的表述。这么做的好处是覆盖面广比如用户用报销提问关键词路能直接命中文档里的报销流程向量路能捞到语义相关的费用申请规范。两路结果融合用 RRF 排序算法核心思想是让在多个结果集里排名都靠前的文档排到前面。RRF 的好处是它对绝对分数不敏感不需要做分数归一化工程实现简单。实际体验下来多路召回加 RRF 比单纯向量检索的准确率高不少尤其是专业术语多的内部文档关键词路的贡献非常关键。如果部署的资源允许还可以开启重排序模块用专门的 rerank 模型对召回结果做二次精排精确度还有提升空间但普通场景下默认的融合排序已经足够。5.4 第一批测试文档的验证方法知识库建好后我建议不要急着把所有资料灌进去先用 20 到 30 份测试文档跑通链路。选一些结构各异的内容一个 PDF 管理制度、一个 Markdown 技术方案、一个 Word 操作手册。上传后观察解析状态再到知识库的文档列表里检查切分数量。然后直接在问答页面提问问题要覆盖明确关键词和模糊描述两类。明确关键词的比如报销流程模糊描述比如我要给客户开票怎么走两种都能从知识库捞到相关内容这批知识库才算合格。6. 问答效果调优从答非所问到有理有据6.1 回答不准确时先查召回还是先查提示词如果我告诉你调优的第一刀先落在召回而不是提示词很多人会意外。实际上大多数回答错误的根因是根本检索不到相关内容大模型再强也无中生有。我的排查链路是固定的先进知识库管理页面用同一个问题搜一下直接看召回出来的文档片段摘要。如果片段跑偏了说明索引、切分或查询本身有问题如果片段是对的那问题才出在大模型提示词或者参数设置上。这个排查习惯帮我避免了很多无效调参。曾经遇到一种情况问项目立项流程出来的答案驴唇不对马嘴我调了半天提示词后来才发现是文档切分时把立项流程拆散到了多个块里召回总是不完整后来重新设置切分规则才解决。6.2 调整召回数量和相似度阈值召回数量也就是最终送入大模型的片段数量是影响答案质量的关键参数。默认值经常偏小我调优时一般是先把它加大到能覆盖多个相关片段同时要控制在大模型上下文窗口能承载的范围内。具体调大多少取决于你用的本地模型的上下文长度。7B 模型通常能容纳的上下文在 8K 到 32K tokens 之间知识片段留足空间给自己别一次喂太多导致模型忽略关键信息。相似度阈值同样要斟酌。阈值设高了语义稍微偏离的问题就检索不到内容阈值设低了召回一堆无关片段大模型会把干扰信息当事实。我的做法是先保持一个较低的阈值看召回率通过问答验证答案准确性再逐步收紧找到平衡点。这个过程没有标准答案每个知识库的文档风格和术语浓度都不一样只能靠实测标定。6.3 提示词工程和温度参数的实际效果召回没问题之后回答不佳基本出在提示词。WeKnora 里可以自定义系统提示词我调优时把提示词定成了这样几个原则明确角色身份让它作为企业内部知识助手约束回答来源要求答案基于提供的知识片段设置边界如果知识片段里没有相关内容就明确说不知道不要编造要求必要时引用原文出处。温度参数直接影响回答的稳定程度。企业内部问答场景我建议把温度压到比较低的水平比如 0.2 左右让答案偏向确定性和事实性。之前试过用默认的高温参数跑知识问答同样的流程问题每次回答的表述都不一样个别时候还会多出上下文里没有的所谓细节降到低温后明显收敛。6.4 具一个调优前后的对比实例拿团队里真实的一个问题来验证新员工入职第一周要做哪些事调优前知识库虽然上传了《新人入职指南》和《设备申请流程》但因为相似度阈值偏高、召回数偏少答案只提到了领电脑完全没覆盖账号开通和制度培训。调整了召回数量并降低阈值之后同一个问题给出的答案把入职指引里的账号申请、设备领取、制度培训、导师对接四个环节全部列出来还标注了各流程对应的文档名称。这种肉眼可见的差异立刻说服了团队里的质疑者也让后续调优有了基准。7. 翻车记录部署和日常使用中踩过的坑7.1 ES 容器反复重启和 JVM 内存的纠缠第一次启动整套环境时ES 容器启停好多次日志里明确提示虚拟内存区域的问题解决方式就是前面说的调整系统内核参数。这个问题很多人知道但坑在于修改参数之后没有确认服务重启后是否依然生效我就在重启服务器之后再次遇到 ES 起不来的情况加了系统配置持久化之后才算根治。内存纠缠也很折磨人。ES 启动时如果检测到系统内存不足以分配给它认为合适的默认堆它就会拒绝启动。后来我强制指定了堆大小并且给宿主机留出足够余量给 Ollama两个大家伙才算相安无事。核心心得是这种多组件系统内存分配得明确分工不能全部依赖默认值。7.2 PDF 解析中文乱码和字体缺失PDF 是我踩得最多的类型。某些扫描版 PDF 压根没有文本层解析出来全是乱码这类只能先做 OCR 预处理再上传不是 WeKnora 本身能解决的。另外一些 PDF 在解析时中文字符断裂排查后发现是容器内缺中文字体影响到了文本提取时的 Unicode 映射。解决方式是在系统运行的容器里补装中文字体包装完重启相关服务。之后中文 PDF 的解析质量就稳定了。这个坑非常有代表性很多开源系统在 Docker 镜像里默认不带完整字体遇到中文用户就容易出问题处理过一次之后就能举一反三。7.3 上传大文档失败和并发索引瓶颈上传一份 50M 以上的超大 PDF 时前端提示失败查看 Nginx 日志发现是请求体积超过默认的上传限制。修改 Nginx 配置里的上传大小参数同时还要注意后端服务对应的环境变量是否也需要同步调整两头都放开才能真正传上去。并发上传多份文档时出现过部分解析任务长时间排队的情况。这是因为解析任务的队列长度和并发数受配置限制。处理方式是把异步任务并发数适度调大但也要注意别把 CPU 吃满否则 Ollama 推理会跟着变卡。稳定的配置是并发数保持在中低水平让解析和推理错峰抢资源。7.4 长期运行的磁盘治理运行几周后我发现数据盘萎缩得比预期快排查下来大头在 ES 索引备份和 MinIO 里的历史版本文件。ES 的索引快照如果开启自动备份要设置保留周期MinIO 里的重复上传文档也需要定期清理。我因为是测试阶段干脆重建过一次索引和知识库磁盘空间直接回了一大截。生产环境一定要从第一天就规划好备份策略和清理策略别等磁盘满了才去处理。8. 给准备上 WeKnora 的团队几点实在建议8.1 先小范围试跑再铺开推广我们团队的节奏是先在 3 到 5 个人的核心小组里用了两周把知识库内容覆盖到常用流程和项目资料每天收集大家实际问的问题持续调优切分参数和提示词。确认答案质量稳定后才向全团队开放。直接铺开的风险在于第一批体验如果被垃圾回答劝退后面要花几倍精力把人拉回来。小范围试跑阶段反而能积累真实问题用来调优。8.2 OIDC 和权限体系值得投入WeKnora 支持 OIDC 协议意味着可以对接企业已有的统一身份认证体系。对于团队几十个人以上的场景我强烈建议投入时间把这块配置好避免每人一套独立账号离职员工账号残留带来的权限黑洞真的很麻烦。我们对接了企业微信的认证方式之后日常使用体验提升明显权限管理也丢给了专业系统处理。8.3 备份必须从第一天开始最后一定要说的是备份。ES 索引、MySQL 库、MinIO 对象存储三个地方的数据都要纳入备份计划。中间件这么多任何一个的数据损坏都会影响整个知识库。我自己的做法是每天对 MySQL 和 MinIO 做快照ES 索引每周做一次全量快照并保留最近两个版本额外的历史版本及时清理。坚持做下来哪怕哪天真出问题了恢复也就是一小时以内的事。这套系统本质上是在给团队积累可检索的知识资产资产丢了系统再漂亮也没用。