
1. 为什么这次必须把 openJiuwen 在本地跑起来先交代一下背景。之前我在内网环境里临时用过一个在线版本的知识问答工具体验其实还行但那个服务托管在外部数据要经过别人家的服务器很多内部资料根本不敢传上去。后来同事推荐了 openJiuwen说是完全开源、可以本地部署的项目我当时手头正好有一台空闲的办公主机就想着周末把它装好让团队在局域网里直接用。第一次尝试很狼狈照着官网文档一步步点折腾了大半天服务倒是起来了但页面上所有请求都在转圈日志各种报错最后只能删掉重来。这个周末我把它重新捡起来换了思路没有再盲信官网给的“快速开始”而是从版本、依赖、模型服务、配置这几个维度重新拆了一遍前后花了大约六个小时终于把 openJiuwen 稳稳地跑在了本地。这篇文章就把整个过程里踩过的坑、绕开的弯路和最终的有效路径完整写下来。先说一句openJiuwen 是什么。它本质上是一个开源的知识库问答平台可以把你手头的文档、笔记、网页内容导入进去借助本地部署的大模型来做检索和问答。和直接调用在线 API 不同本地部署意味着所有数据都留在自己的机器上适合企业内部资料整理、个人知识库搭建、离线环境下的文档问答这类场景。如果你正打算部署 openJiuwen或者你刚在官网文档里被绕晕了这篇文章应该能帮你省掉至少一整天的排查时间。我把整个流程拆成了几个部分官网信息的甄别、基础环境的准备、本地模型服务的搭建、openJiuwen 本体的安装、运行时的常见问题以及部署之后的一些实际体验。2. 官网文档上的三处“信息雷”2.1 稳定版和开发版的分支陷阱openJiuwen 官网的文档入口其实做得很好看首页明确写着“稳定版”“开发版”两个文档切换按钮但很多人在官网看文档的时候根本不会注意自己处于哪个分支。我第一次就是直接打开了默认的开发版文档里面写了很多新特性的安装方式还引用了尚未合并到正式版本的配置文件字段。这就出了一个很典型的问题开发版的部署步骤要求的环境变量、依赖版本跟稳定版并不一致。等我按照开发版文档装完以后发现项目代码里根本没有对应的配置文件和数据库迁移脚本启动当然是失败。后来我才注意到页面右上角的版本切换切回“稳定版”之后很多最初对不上的东西才对上了。同样的问题也会出现在 GitHub 仓库的 README 上。如果你打开的是默认分支 main看到的可能是最新开发状态而 release 分支或 tag 才是当前稳定发行版。建议你在开始之前先确认自己要用的是哪个版本然后同时锁定官网的文档版本和代码仓库的 tag不要让文档和代码各说各话。2.2 依赖清单里的隐性前提官网的“环境要求”页面写得很简单说什么 Python 3.8 以上、Node.js 14 以上、再加一个数据库就行。这看起来不算复杂但实际上这只是“跑起来”的最低要求不是“稳定运行”的真实条件。我一开始就按照最低要求来结果发现openJiuwen 的检索服务需要用到 Redis 做缓存和任务队列但环境要求里只有在“高级部署”页面才提到前端构建时用到了较新的 Node 特性Node 14 根本编不过去报错信息还很模糊只提示一个语法错误数据库方面虽然支持 SQLite 快速体验但只要并发稍微高一点SQLite 就频繁锁库日志里全是数据库 locked。如果你只是想在本机跑通 demo那 SQLite 简陋配置没问题。但要在局域网里给几个人正常用建议从一开始就把 Redis、PostgreSQL 或者是 MySQL 准备到位后面会少很多麻烦。我在最后给出的部署建议里会把每一步该装什么列清楚。2.3 下载包和 git 仓库的文件不一致官网提供 zip 包下载也提供了 git 克隆入口。我这次第一次用的是从官网下载的 release 压缩包但解压后发现几个后端模块目录是空的里面只有占位说明文件。比较奇怪的是同样的版本通过 git clone 拉下来文件是完整的。这种事情在开源项目里不算罕见发布流程里漏了子模块或者没跑完整构建压缩包生成得仓促。但对我们部署者来说浪费的时间是实打实的。所以我的建议是尽量用 git 标签方式拉代码不要直接下载压缩包。比如git clone --depth 1 --branch v1.2.1 https://github.com/openjiuwen/openjiuwen.git这样至少能保证文件完整以后升级的时候也好切分支。2.4 官方示例配置不能直接复制官网给了很多 .env.example 示例文件但如果你直接cp .env.example .env然后就启动大概率会卡在某个环节。官方示例里很多值填的是占位符比如LLM_API_BASEhttp://localhost:11434/v1看起来没问题但实际模型服务的路径、鉴权方式会因为模型后端不同而不同。另外示例里的数据库连接字符串用的是 Docker 内网地址本地直接跑后端进程时这个地址是没有意义的。正确做法是先理解示例里每个配置项的含义再根据自己的实际环境改。不要怕麻烦把环境变量都过一遍尤其注意端口、路径、密钥这几类。3. 部署前的地基硬件、系统、Python 环境的搭建顺序3.1 硬件怎么选才不亏openJiuwen 本体其实不吃资源真正吃资源的是本地大模型推理。实践下来我建议按模型规模来决定机器配置模型规模参数量最低内存推荐显存适用场景小模型1.5B~3B8G4G简单问答、文本分类中模型7B~8B16G8G知识库检索问答、摘要大模型13B~14B32G16G多文档长文本推理我这次用的是 7B 量级的量化模型配的是 16G 内存 8G 显存的机器跑 openJiuwen 的问答功能基本够用。文档检索时的响应时间在 5 到 15 秒之间属于可以接受的范围。如果机器内存太小建议先别碰 7B 以上的模型老老实实先用小模型验证流程。3.2 用 virtualenv 隔离环境避免系统 Python 被搞乱很多部署教程都直接让你pip install然后在系统 Python 里安装一堆依赖。这样做短期没问题但一旦你之后要装别的 Python 项目版本冲突和系统污染会非常恶心。建议一开始就建一个独立的虚拟环境。打开终端先装好 python3-venv 和 pipsudo apt update sudo apt install -y python3-venv python3-pip git build-essential然后创建虚拟环境mkdir -p /opt/openjiuwen cd /opt/openjiuwen python3 -m venv venv source venv/bin/activate之后再安装任何 Python 依赖都在这个虚拟环境里操作退出环境就用deactivate。这一步看起来多花了五分钟后续能帮你挡掉大量版本冲突问题。3.3 提前部署 Postgres 和 Redis如果只是本机测试用 SQLite 当然省事但是 openJiuwen 在初始化知识库索引、批量导入文档的时候会频繁读写数据库。SQLite 的并发写能力很弱一旦导入任务和其他查询同时发生几乎必现锁库。实测中我遇到过多次database is locked后来换成 PostgreSQL 就没有再出现。如果你不熟悉 PostgreSQL可以用 Docker 快速起一个docker run -d --name openjiuwen-pg \ -e POSTGRES_USERopenjiuwen \ -e POSTGRES_PASSWORDopenjiuwen_pass \ -e POSTGRES_DBopenjiuwen \ -p 5432:5432 \ postgres:14Redis 更简单docker run -d --name openjiuwen-redis \ -p 6379:6379 \ redis:7这里有一点要提醒如果公司网络环境不允许直接拉 Docker Hub 镜像提前确认一下内网有没有镜像仓库别到了最后一步才傻眼。如果 Docker 也不能用可以装原生的 PostgreSQL 和 Redis只是排障的难度会高一些。4. 本地模型服务准备没有模型openJiuwen 就是个空壳openJiuwen 本身不内置大模型它只是一个平台需要对接模型推理服务。你可以选择对接线上 API但既然目标是本地部署大部分人的选择自然是本地推理引擎。我这次用的是 Ollama 配合 7B 量化模型流程方便资源占用也比较友好。4.1 用 Ollama 还是其他推理方案关于推理后端的选择我在部署前简单列过几个方案方案安装难度显存要求适合程度Ollama低单机最友好低个人和中小团队首选vLLM中需要较高配置高高并发生产环境llama.cpp中需要自己编译灵活纯 CPU 场景对于大多数人来说Ollama 是性价比最高的选择。它支持 OpenAPI 兼容接口openJiuwen 直接通过 HTTP 调用就行不需要额外写适配代码。安装也就一条命令curl -fsSL https://ollama.com/install.sh | sh4.2 模型拉取失败的应对方式装着装着一个常见问题就来了模型下载到一半失败比如网络中断、磁盘空间不足、进度条卡住不动。我第一次拉 7B 模型的时候在 87% 的地方卡了十几分钟最后直接报错退出。这里有几个实用的处理方式第一使用环境变量指定模型存储目录避免默认位置空间不够export OLLAMA_MODELS/data/ollama-models ollama pull qwen2.5:7b-instruct-q4_K_M第二如果下载经常中断可以分多个终端观察日志或者直接用ollama list查看已下载部分。Ollama 对断点续传的支持不太好重试也是一种办法。比较粗暴但有效的方式是删除残留的 manifest 和 blob 文件之后重新拉。第三模型下载需要占用网卡如果你的机器上有大量其他流量很可能下载会很慢。尽量选择网络比较空闲的时间段。4.3 模型接口和 openJiuwen 的对接模型服务跑起来以后要确认一下接口地址是否可以被 openJiuwen 访问。默认情况下 Ollama 只监听 127.0.0.1如果你要在一台机器上部署 openJiuwen 和 Ollama那没问题但如果你想让局域网里其他机器也通过 openJiuwen 访问模型服务就需要开放监听地址。修改/etc/systemd/system/ollama.service中的启动参数或者直接运行时指定OLLAMA_HOST0.0.0.0 ollama serve然后调用一下接口验证是否可用curl http://localhost:11434/v1/chat/completions \ -H Content-Type: application/json \ -d {model:qwen2.5:7b-instruct-q4_K_M,messages:[{role:user,content:你好}]}如果返回了正常的 JSON说明模型服务正常。openJiuwen 配置里的LLM_API_BASE就填这个地址LLM_API_KEY可以填任意非空字符串因为 Ollama 不检查 API Key。5. openJiuwen 安装的完整流程从 clone 到界面亮起来5.1 获取代码并锁定版本这一步是整个部署里最简单但也最容易埋雷的。我强烈建议使用 git clone 而不是下载压缩包。代码如下cd /opt/openjiuwen git clone --depth 1 --branch stable https://github.com/openjiuwen/openjiuwen.git app cd app如果你不知道有哪些稳定分支可以先不指定分支拉取然后用git tag列出所有版本挑一个看起来比较新的稳定版本。5.2 后端依赖安装与配置进入项目目录后确认虚拟环境依然处于激活状态然后安装后端依赖pip install --upgrade pip pip install -r requirements.txt这里有一个小技巧如果requirements.txt比较大安装过程很慢可以考虑用国内镜像源加速pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple接下来复制环境变量模板cp .env.example .env修改.env中这几个核心配置项DB_ENGINEpostgresql DB_HOST127.0.0.1 DB_PORT5432 DB_USERopenjiuwen DB_PASSWORDopenjiuwen_pass DB_NAMEopenjiuwen REDIS_HOST127.0.0.1 REDIS_PORT6379 LLM_PROVIDERollama LLM_API_BASEhttp://127.0.0.1:11434/v1 LLM_API_KEYsk-local LLM_MODELqwen2.5:7b-instruct-q4_K_M5.3 数据库迁移与初始数据依赖装好、配置写好后就要初始化数据库结构。大多数 Python Web 项目会提供管理命令openJiuwen 也是一样flask db upgrade python manage.py init_role python manage.py create_admin --email adminexample.com --password yourpassword如果你急着测试也可以先用 SQLite 模式跳过 PostgreSQL 的配置但前面提到过别在高并发场景下用 SQLite 硬撑。5.4 前端构建与服务启动openJiuwen 的前端是独立构建的如果你从源码启动需要先编译静态资源cd frontend npm install npm run build cd ..前端构建完成后后端有两种启动方式。测试时直接跑开发服务器python manage.py runserver --host 0.0.0.0 --port 8000真实使用时建议用 gunicorngunicorn -w 4 -b 0.0.0.0:8000 app:create_app()打开浏览器访问http://localhost:8000用刚才创建的账号登录openJiuwen 的主界面就应该能看到了。到这一步整个本地部署的核心流程就算跑通了。6. 启动和运行中绕不开的典型问题6.1 我实际遇到过的报错和处理方式这一节我把问题和处理方式单独拿出来说因为这些问题非常典型几乎每个部署 openJiuwen 的人都会碰到至少一两个症状原因处理方法启动后访问 502gunicorn 没起来或端口被占用先看日志再确认port配置杀掉占用进程登录后无限跳转SECRET_KEY 为空或跨域配置错误在.env里生成随机的 SECRET_KEY导入文档时转圈Redis 没启动或 worker 没起来确认 Redis 进程启动 celery worker问答返回空内容模型名填错或模型没下载完ollama list检查模型ollama pull补齐上传文件超时Nginx 上传大小限制配置client_max_body_size或直接用开发服务器测试调用模型接口报 401服务端配置的 API Key 与请求头不匹配检查.env里的 LLM_API_KEY6.2 白屏问题的排查链前端页面白屏是我最初遇到最头疼的问题看起来啥也没显示但后端日志又没报错。排查思路是这样的先打开浏览器开发者工具看控制台的报错。如果是加载 JS 资源 404说明collectstatic没执行或者静态目录配置不对如果是跨域报错检查后端的CORS_ALLOWED_ORIGINS是否包含了你访问的域名和端口如果控制台没有报错但页面空白可能是前端构建产物为空重新执行npm run build确认dist目录里有内容。6.3 日志怎么读才有用前端交互出现问题大多数时候信息藏在后端日志里。启动 gunicorn 时加上--access-logfile - --error-logfile -可以把请求日志打到终端gunicorn -w 4 -b 0.0.0.0:8000 --access-logfile - --error-logfile - app:create_app()日志中如果出现Traceback直接定位最后一个异常信息如果是EOFError、connection reset大概率是反向代理配置问题。如果日志正常但功能异常再看 openJiuwen 自己的应用日志一般会输出在每个模块自己的目录下。6.4 Docker 方式部署时的注意点很多人会自然考虑用 docker compose 做一键部署。之前的失败也试过这种方式但没有成功原因大多卡在模型服务如何与容器通信的问题上。容器里的 openJiuwen 访问宿主机上的 Ollama地址不能写localhost要写host.docker.internal:11434或者在启动容器时加--networkhost。用 Docker 部署确实能省下环境配置的功夫但排查容器的网络、数据卷挂载和日志要绕不少路。如果你是第一次部署我更建议直接在宿主机上跑等流程彻底走通了再考虑容器化。7. 部署成功之后我实际是怎么用它的7.1 把团队文档变成可检索的知识库服务跑起来之后的用途才是我真正关心的。我主要把 openJiuwen 用在了内部资料的整理上。以前我们团队的几十个文档散落在不同的网盘、本地目录里想找一个细节经常要翻半天。现在统一导入到 openJiuwen 里再用本地模型做检索增强问答同事直接问“去年第三季度的项目验收报告里提到的那几个问题有哪些”就能拿到准确答案。这一步的意义在于文档不是存起来就完事还得让人能找到、能复用。openJiuwen 在这个过程中扮演的角色就是连接文档和大模型的中间层它负责切分文档、建立索引、召回片段然后把片段交给模型生成回答。本地部署后这些内容都不会出内网安全边界清晰很多。7.2 运行一周后我给自己的三个提醒第一备份要提前做。openJiuwen 的数据分别在数据库和向量索引目录里我吃过一次备份不完整的亏恢复之后发现历史导入的文档全丢了。现在我会定期把 Postgres 的 dump 和向量索引目录整个打包备份放到专门的备份盘。第二模型不是越大越好。我一开始觉得 7B 不够想上 14B 的模型结果显存扛不住问答响应直接变成半分钟以上体验反而更差。后来把模型量化等级调低控制上下文长度响应速度立刻上了个台阶。如果你也不确定该用哪档模型可以先从 4bit 量化的小模型测起再逐步往上调整。第三升级要克制。 openJiuwen 更新频率并不算特别高但每次更新如果动了数据库结构升级前最好先在另一台机器上测试。盲升级导致数据迁移失败、服务起不来的案例在我认识的开源项目用户里已经见了好几个。7.3 如果要重新来一遍我会怎么做如果再让我从零部署一次 openJiuwen我的快捷键是先花二十分钟读官网的稳定版文档和项目的 issues 列表把版本、数据库、模型后端这三个关键决定先想清楚再去碰代码。不要急着git clone也不要直接pip install。部署这种项目真正的成本从来不是执行命令的时刻而是排错和返工的精力消耗。下载模型、配置接口、初始化数据库、验证问答链路每一步都有各自的坑但只要把顺序理清踩坑一次之后就能形成自己的稳定流程。这篇文章写下来也是希望后来者能少走几段我走过的弯路。