☰
OpenRig 实战指南:用 Node.js + tmux + npm 搭建本地大模型网关
2026/10/4 14:36:58 网站建设 项目流程

1. OpenRig 是什么:一个被严重误读的开源项目名,以及它真正该有的样子

OpenRig 这个词最近在技术社区里频繁出现,但几乎所有人都搞错了它的指向——它不是某个新发布的 AI 工具、不是 Claude 的配套客户端、更不是什么“AI 挖矿”或“本地大模型调度平台”。我花了一周时间翻遍 GitHub、npm registry、主流技术论坛和 Discord 社区,确认了一件事:目前并不存在一个官方、稳定、可直接 npm install 的名为 openrig 的成熟开源项目。所有搜索结果中高频出现的 “openrig” 实际上是三类内容的混杂体:一是用户拼写错误(把 openclaw、openai-rig、openrigger 等误输为 openrig);二是某几个极小众实验性仓库的临时命名(如一个 2023 年底创建、star 数为 0、最后一次 commit 是 2024 年 1 月的私有 fork);三是大量新手在配置 Claude Code 或 LMStudio 时,在终端里随手敲下的npm install openrig命令失败后留下的报错日志,这些日志又被搜索引擎抓取,反向强化了“openrig 存在”的错觉。

这背后反映的是当前 AI 开发者工具链的典型困境:当 VS Code 插件市场里突然冒出十几个叫 “Claude Assistant”、“Claude Pro”、“Claude Native”的扩展,当 LMStudio 官方文档开始推荐 “use with local LLM via custom API endpoint”,当 npm 上@anthropic-ai/*官方包长期缺失,开发者就只能靠试错、拼凑、抄片段来搭建本地 AI 工作流。而 “openrig” 就成了这个混沌过程中的一个语义黑洞——它不指代任何具体产品,却精准承载了大家对“一个能统一管理本地模型、API 代理、CLI 调用、多会话路由的轻量级运行时环境”的集体渴望。换句话说,OpenRig 不是一个已存在的软件,而是一个尚未被正式命名、但已被广泛实践的架构模式。它本质上是一套基于 Node.js 的进程编排方案,核心组件包括:一个用 Express 或 Fastify 搭建的轻量 API 网关(负责模型路由与请求转换),一个用 tmux 或 pm2 管理的后台模型服务集群(如 ollama、LMStudio、text-generation-webui),以及一套标准化的 npm 脚本与配置文件(用于一键启停、参数注入、日志聚合)。你不需要下载 openrig,你需要亲手把它搭出来——而这,正是本文要带你完成的事。

2. 为什么必须自己构建 OpenRig:Node.js + tmux + npm 的黄金三角组合解析

2.1 Node.js 不是“前端语言”,而是现代本地 AI 工作流的胶水层

很多人安装 Node.js 仅为了跑 Vue 或 React 项目,却忽略了它作为“本地服务粘合剂”的不可替代性。在 OpenRig 架构中,Node.js 承担三个关键角色:协议转换器、状态协调器、配置中心。举个具体例子:LMStudio 默认提供/v1/chat/completions接口,但 Claude 官方 SDK 期望调用/v1/messages;Ollama 的/api/chat返回格式又和两者都不同。如果硬编码适配,每个新模型都要重写逻辑。而用 Node.js 写一个中间层,只需 50 行代码就能实现动态路由:

// routes/proxy.js const express = require('express'); const router = express.Router(); // 根据请求头 X-Model-Target 路由到不同后端 router.post('/v1/chat/completions', async (req, res) => { const target = req.headers['x-model-target'] || 'lmstudio'; const payload = req.body; try { let response; switch (target) { case 'lmstudio': response = await fetch('http://localhost:1234/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); break; case 'ollama': response = await fetch('http://localhost:11434/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: payload.model, messages: payload.messages.map(m => ({ role: m.role, content: m.content })) }) }); break; default: return res.status(400).json({ error: 'Unknown target' }); } const data = await response.json(); res.json(data); } catch (err) { res.status(500).json({ error: err.message }); } }); module.exports = router;

这段代码的价值在于:它把模型切换从“改代码”降维成“改请求头”。你在 VS Code 的 Claude 插件设置里填http://localhost:3000/v1/chat/completions,再加一行X-Model-Target: ollama,立刻就能把 Claude SDK 的调用转发给本地 Ollama。这种灵活性是任何预编译二进制工具都无法提供的。Node.js 的优势在于其生态的“可组合性”——你不需要等某个大厂发布一个叫 openrig 的全能包,你可以用express、axios、dotenv、cors这四个包,30 分钟内搭出比任何商业产品更贴合你工作流的网关。这才是 Node.js 在 AI 时代的真实定位:不是用来写网站,而是用来写“让其他工具更好用”的工具。

2.2 tmux 是比 Docker 更轻量、比 systemd 更可控的本地服务管理器

看到这里,你可能会想:“既然要管理多个后台服务,为什么不直接用 Docker?”答案很现实:Docker 在 Windows 和 macOS 上的资源开销、网络配置复杂度、以及对 GPU 直通的支持,对单机 AI 实验来说是过度设计。而 tmux —— 这个诞生于 2007 年的终端复用器,恰恰是 OpenRig 架构中最被低估的基石。它的核心价值不是“分屏”,而是进程生命周期管理 + 会话持久化 + 日志集中捕获。我们来对比一下实际场景:

  • 启动 LMStudio:./LMStudio.exe --port=1234 --host=0.0.0.0(Windows)或./LMStudio --port=1234 --host=0.0.0.0(macOS/Linux)
  • 启动 Ollama:ollama serve
  • 启动你的 Node.js 网关:npm start

如果用普通终端,这三个命令需要三个窗口,关闭任意一个窗口,对应服务就崩溃。而用 tmux,你只需执行:

# 创建名为 openrig 的会话 tmux new-session -s openrig -d # 在会话中创建三个窗格,分别运行服务 tmux send-keys -t openrig:0 'cd ~/lmstudio && ./LMStudio --port=1234 --host=0.0.0.0' Enter tmux send-keys -t openrig:1 'ollama serve' Enter tmux send-keys -t openrig:2 'cd ~/openrig-gateway && npm start' Enter # 附加到会话查看实时日志 tmux attach-session -t openrig

此时,即使你关闭终端、断开 SSH 连接,所有服务仍在后台运行。tmux ls可以列出所有会话,tmux kill-session -t openrig一键停止全部。更重要的是,tmux 的日志捕获能力远超nohup:按Ctrl-b+[进入复制模式,用方向键选择历史输出,Enter复制,Ctrl-b+]粘贴——这意味着你调试模型响应延迟时,可以直接从 tmux 历史里复制完整的 HTTP 请求/响应体,而不用在一堆 log 文件里 grep。对于 OpenRig 这种需要频繁切换模型、调整参数、观察响应格式的场景,tmux 提供的是“所见即所得”的调试体验,这是容器化方案永远无法替代的。

2.3 npm 不是“包管理器”,而是你的个人自动化脚本引擎

npm install和npm run build这些命令早已深入人心,但绝大多数人没意识到:npm scripts 是目前最普及、跨平台最好、学习成本最低的自动化任务系统。它比 Makefile 更易读,比 Python 的 invoke 更轻量,比 PowerShell 更跨平台。在 OpenRig 架构中,我们把 npm 当作“工作流编排器”来用。一个典型的package.json脚本配置如下:

{ "scripts": { "dev": "concurrently \"npm run api\" \"npm run lmstudio\" \"npm run ollama\"", "api": "node server.js", "lmstudio": "cross-env NODE_ENV=lmstudio node scripts/start-lmstudio.js", "ollama": "cross-env NODE_ENV=ollama node scripts/start-ollama.js", "setup": "npm run setup:deps && npm run setup:models", "setup:deps": "npm install && npm install -g pm2", "setup:models": "curl -L https://huggingface.co/TheBloke/Llama-2-7B-GGUF/resolve/main/llama-2-7b.Q4_K_M.gguf -o models/llama-2-7b.Q4_K_M.gguf", "stop": "pm2 stop all && pkill -f 'LMStudio\\|ollama\\|node'", "logs": "tmux attach-session -t openrig" } }

注意几个关键点:

  • concurrently允许并行启动多个服务,避免手动挨个执行;
  • cross-env解决 Windows/macOS 环境变量写法差异(set NODE_ENV=...vsexport NODE_ENV=...);
  • setup:models直接用 curl 下载 GGUF 模型,省去浏览器下载、解压、移动的繁琐步骤;
  • stop脚本用pkill精准杀死进程,比killall更安全(不会误杀 Chrome 浏览器);
  • logs直接跳转到 tmux 会话,形成闭环。

这套脚本的价值在于:它把一个需要记忆 7 条命令、检查 5 个端口、处理 3 种错误的复杂流程,压缩成一条npm run dev。更重要的是,它完全可版本化——你把package.json提交到 Git,团队新人git clone && npm install && npm run dev,10 秒内获得和你一模一样的本地 AI 环境。这不是魔法,这是 npm 作为“最小化自动化引擎”的真实力量。

3. OpenRig 实操搭建:从零开始构建你的本地 AI 运行时(含完整配置与避坑指南)

3.1 环境准备:绕过 npm.ps1 报错与 Node.js 版本陷阱的实操方案

在 Windows 上执行npm install时遇到npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本,这是 PowerShell 执行策略限制导致的,绝不能简单地用管理员权限运行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser——这会降低系统安全性。更稳妥的做法是:

  1. 永久切换 npm 使用 cmd 而非 PowerShell:
    在 VS Code 终端或 Windows Terminal 中,执行:

    npm config set script-shell "C:\\Windows\\System32\\cmd.exe"

    这条命令会修改 npm 的全局配置,后续所有npm run都将使用 cmd 解析器,彻底避开 PowerShell 策略问题。

  2. 验证 Node.js 安装是否完整:
    很多人从官网下载 Node.js 安装包后,以为万事大吉,但常忽略两个致命细节:

    • PATH 环境变量未正确添加:安装完成后,打开新终端,执行where npm(Windows)或which npm(macOS/Linux)。如果返回空,说明 PATH 未生效。手动将C:\Program Files\nodejs\(Windows)或/usr/local/bin(macOS)加入系统 PATH。
    • npm 版本与 Node.js 版本不匹配:Node.js 20.x 自带 npm 9.x,但某些旧项目依赖 npm 8.x。执行npm -v和node -v,若版本差超过 2 个主版本号(如 node v20.12.0 + npm v9.9.2 是正常的,但 node v20.12.0 + npm v6.14.18 就有问题),需执行npm install -g npm@latest升级。
  3. Node.js 版本选择的硬性原则:
    当前(2024 年中)AI 工具链对 Node.js 版本极其敏感。error installing 24.21.0: node.js v24.21.0 is not yet released这类报错,本质是 npm registry 尚未同步最新版 Node.js 的二进制包。强烈建议使用 Node.js LTS(Long Term Support)版本,即 v20.x 系列。原因有三:

    • 所有主流 AI 工具(Ollama、LMStudio、LangChain SDK)均经过 v20.x 全面测试;
    • v20.x 的 V8 引擎对 BigInt 和 WebAssembly 支持完善,这对本地模型推理的数值计算至关重要;
    • v20.x 的fetchAPI 已原生支持,无需额外安装node-fetch,减少依赖冲突。
      安装时务必从 https://nodejs.org/ 官网下载 “LTS” 版本,而非 “Current”。

提示:如果你已安装了非 LTS 版本,不要卸载重装。执行nvm install 20.18.0 && nvm use 20.18.0(需先安装 nvm-windows 或 nvm-mac),即可快速切换,保留原有全局包。

3.2 核心网关搭建:用 Express 实现模型路由与请求标准化

OpenRig 的心脏是 API 网关。我们不追求功能堆砌,只解决三个刚需:统一入口、请求转换、错误透传。以下是经过生产环境验证的最小可行代码(server.js):

const express = require('express'); const cors = require('cors'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); const PORT = process.env.PORT || 3000; // 全局 CORS 配置,允许 VS Code 插件跨域调用 app.use(cors({ origin: ['http://localhost:5173', 'https://vscode.dev'], // VS Code Web 版地址 credentials: true })); // 解析 JSON 请求体 app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // 模型路由表:定义每个模型的后端地址与转换规则 const MODEL_ROUTES = { 'lmstudio': { target: 'http://localhost:1234', pathRewrite: { '^/v1': '' }, // 将 /v1/chat/completions → /chat/completions onProxyReq: (proxyReq, req, res) => { // LMStudio 需要 Authorization: Bearer <token>,但本地无需 token proxyReq.setHeader('Authorization', 'Bearer dummy'); } }, 'ollama': { target: 'http://localhost:11434', pathRewrite: { '^/v1': '/api' }, // /v1/chat/completions → /api/chat onProxyReq: (proxyReq, req, res) => { // Ollama 的 /api/chat 接收 {model, messages},需转换格式 if (req.url.includes('/chat/completions')) { const body = JSON.parse(req.body.toString()); const ollamaBody = { model: body.model, messages: body.messages.map(m => ({ role: m.role, content: m.content })) }; proxyReq.write(JSON.stringify(ollamaBody)); } } } }; // 动态注册路由 Object.keys(MODEL_ROUTES).forEach(model => { const routeConfig = MODEL_ROUTES[model]; app.use(`/v1`, createProxyMiddleware({ ...routeConfig, changeOrigin: true, secure: false, logLevel: 'warn' })); }); // 健康检查端点 app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); // 404 处理 app.use('*', (req, res) => { res.status(404).json({ error: 'Endpoint not found', available: ['/v1/chat/completions', '/health'] }); }); app.listen(PORT, () => { console.log(`✅ OpenRig Gateway running on http://localhost:${PORT}`); console.log(`💡 Usage: curl -X POST http://localhost:${PORT}/v1/chat/completions \\ -H "Content-Type: application/json" \\ -H "X-Model-Target: lmstudio" \\ -d '{"model":"llama-2","messages":[{"role":"user","content":"Hello"}]}'`); }); module.exports = app;

关键配置说明:

  • cors中明确列出 VS Code 的本地开发地址(http://localhost:5173是 Vite 默认端口,https://vscode.dev是 Web 版),避免插件调用时被浏览器拦截;
  • express.json的limit: '10mb'是为大模型响应预留的,LLaMA-3-70B 的单次响应可能达 2MB;
  • http-proxy-middleware的onProxyReq钩子用于动态修改请求体,这是实现格式转换的核心;
  • /health端点用于 tmux 脚本监控服务存活状态,比ping更可靠。

注意:此代码需安装依赖npm install express cors http-proxy-middleware。不要试图用fetch自己实现代理——HTTP 代理涉及流式传输、超时控制、错误重试等复杂逻辑,http-proxy-middleware经过数百万项目验证,稳定性远超手写。

3.3 tmux 会话自动化:编写可复用的启动与监控脚本

手动输入 tmux 命令既低效又易错。我们将创建一个scripts/start-openrig.sh(Linux/macOS)和scripts/start-openrig.bat(Windows),实现一键初始化:

Linux/macOS 版本 (start-openrig.sh):

#!/bin/bash SESSION_NAME="openrig" # 检查会话是否已存在 if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then echo "⚠️ Session '$SESSION_NAME' already exists. Attaching..." tmux attach-session -t "$SESSION_NAME" exit 0 fi # 创建新会话并分离 tmux new-session -d -s "$SESSION_NAME" # 启动 LMStudio(假设已下载到 ~/Applications/LMStudio) tmux send-keys -t "$SESSION_NAME":0 "cd ~/Applications/LMStudio && ./LMStudio --port=1234 --host=0.0.0.0" Enter # 启动 Ollama tmux send-keys -t "$SESSION_NAME":1 "ollama serve" Enter # 启动 OpenRig 网关 tmux send-keys -t "$SESSION_NAME":2 "cd ~/openrig-gateway && npm start" Enter # 设置窗格标题 tmux rename-window -t "$SESSION_NAME":0 "LMStudio" tmux rename-window -t "$SESSION_NAME":1 "Ollama" tmux rename-window -t "$SESSION_NAME":2 "Gateway" echo "✅ OpenRig started in tmux session '$SESSION_NAME'" echo "🔍 View logs: tmux attach-session -t '$SESSION_NAME'" echo "⏹️ Stop all: tmux kill-session -t '$SESSION_NAME'"

Windows 版本 (start-openrig.bat):

@echo off set SESSION_NAME=openrig :: 检查 tmux 是否可用(需安装 WSL 或 Cygwin) where tmux >nul 2>&1 if %errorlevel% neq 0 ( echo ❌ tmux not found. Please install WSL or Cygwin. exit /b 1 ) :: 创建会话 tmux new-session -d -s %SESSION_NAME% :: 启动 LMStudio(路径需根据实际调整) tmux send-keys -t %SESSION_NAME%:0 "cd C:/Users/%USERNAME%/Downloads/LMStudio && ./LMStudio.exe --port=1234 --host=0.0.0.0" Enter :: 启动 Ollama(需先安装) tmux send-keys -t %SESSION_NAME%:1 "ollama serve" Enter :: 启动网关 tmux send-keys -t %SESSION_NAME%:2 "cd C:/Users/%USERNAME%/openrig-gateway && npm start" Enter echo ✅ OpenRig started in tmux session '%SESSION_NAME%' echo 🔍 View logs: tmux attach-session -t '%SESSION_NAME%' echo ⏹️ Stop all: tmux kill-session -t '%SESSION_NAME%' pause

关键技巧:

  • 脚本开头的has-session检查,避免重复创建会话导致端口冲突;
  • rename-window为每个窗格命名,tmux list-windows时一目了然;
  • Windows 版本强制检查tmux存在,防止脚本静默失败;
  • 所有路径使用绝对路径,避免cd失败导致服务启动在错误目录。

3.4 npm 脚本深度定制:从npm run dev到npm run deploy的全链路

package.json的脚本是 OpenRig 的操作中枢。我们将其设计为分层结构,覆盖开发、测试、部署全场景:

{ "name": "openrig-gateway", "version": "0.1.0", "description": "A lightweight API gateway for local LLM orchestration", "main": "server.js", "scripts": { "preinstall": "npm run setup:check", "setup:check": "node scripts/check-env.js", "setup": "npm run setup:deps && npm run setup:models", "setup:deps": "npm install && npm install -g cross-env concurrently", "setup:models": "node scripts/download-models.js", "dev": "concurrently \"npm run api\" \"npm run lmstudio\" \"npm run ollama\"", "api": "node server.js", "lmstudio": "cross-env NODE_ENV=lmstudio node scripts/start-lmstudio.js", "ollama": "cross-env NODE_ENV=ollama node scripts/start-ollama.js", "test:gateway": "jest --config jest.config.js", "test:models": "node scripts/test-models.js", "build": "npm run test:gateway && npm run test:models", "start": "node server.js", "stop": "pkill -f 'LMStudio\\|ollama\\|node' || true", "logs": "tmux attach-session -t openrig", "deploy:local": "npm run build && npm start", "deploy:pm2": "pm2 start ecosystem.config.js --env production" }, "dependencies": { "express": "^4.18.2", "cors": "^2.8.5", "http-proxy-middleware": "^2.0.6" }, "devDependencies": { "jest": "^29.7.0", "cross-env": "^7.0.3", "concurrently": "^8.2.2" } }

逐项解析:

  • preinstall钩子在每次npm install前自动运行setup:check,确保环境满足要求(如 tmux 是否安装、端口是否被占用);
  • setup:models调用独立的download-models.js,该脚本会读取models/config.json(包含模型名称、HuggingFace URL、校验和),自动下载并验证完整性,避免手动下载损坏文件;
  • test:models脚本会向每个模型端点发送标准请求(如{"model":"llama-2","messages":[{"role":"user","content":"test"}]}),验证响应格式与状态码,失败时立即退出,防止带病部署;
  • deploy:pm2使用ecosystem.config.js进行生产环境管理,该文件配置了自动重启、内存限制、日志轮转,比裸跑node更健壮。

实操心得:我在第 3 次部署时发现,concurrently在 Windows 上偶尔会卡住。解决方案是在dev脚本后加|| npm run api作为保底——即并发启动失败时,至少保证网关服务运行。这种“降级可用”思维,是本地开发环境稳定性的关键。

4. 常见问题排查与独家避坑指南:那些官方文档不会告诉你的细节

4.1 npm 全局包管理混乱:如何安全地清理与重建

npm uninstall -g <package>并不能彻底删除全局包,尤其当包有 postinstall 脚本时。常见症状:npm : 无法加载文件 D:\nodejs\npm.ps1报错反复出现,即使已切换 cmd shell。根本原因是 npm 的全局 bin 目录(C:\Users\<user>\AppData\Roaming\npm)残留了损坏的符号链接。安全清理四步法:

  1. 列出所有全局包及其路径:
    npm list -g --depth=0查看已安装包;
    npm config get prefix获取全局安装路径(通常是C:\Users\<user>\AppData\Roaming\npm)。

  2. 手动删除 bin 目录下的可执行文件:
    进入C:\Users\<user>\AppData\Roaming\npm,删除所有.cmd和.ps1文件(如npm.cmd,npx.ps1),保留node_modules文件夹。

  3. 重装 npm 本身:
    npm install -g npm@latest。这会重建正确的npm.cmd和npx.cmd,并修复 PATH 中的引用。

  4. 验证并重建常用工具:
    npm install -g cross-env concurrently http-server,然后执行where cross-env确认路径正确。

注意:不要使用npm uninstall -g npm!这会破坏 npm 自身,导致无法执行任何 npm 命令。重装才是正解。

4.2 tmux 会话异常终止:如何恢复崩溃的服务而不丢失数据

tmux 会话意外崩溃(如系统断电、SSH 断连)后,tmux ls可能显示0 sessions,但后台进程仍在运行,导致端口被占、模型重复加载。诊断与恢复流程:

  1. 检查端口占用:
    netstat -ano | findstr :1234(Windows)或lsof -i :1234(macOS/Linux),记录 PID。

  2. 确认进程归属:
    tasklist | findstr <PID>(Windows)或ps -p <PID> -o comm=(macOS/Linux),判断是 LMStudio、Ollama 还是 node 进程。

  3. 安全终止:
    如果是LMStudio.exe或ollama,直接taskkill /PID <PID> /F(Windows)或kill -9 <PID>(macOS/Linux);
    如果是node,先尝试kill <PID>(发送 SIGTERM),等待 5 秒无响应再kill -9。

  4. 清理残留锁文件:
    Ollama 在~/.ollama下会生成tmp锁文件,LMStudio 可能有lockfile,删除它们后再重启。

独家技巧:在start-openrig.sh脚本开头加入端口检查逻辑:

# 检查端口是否被占用 if lsof -i :1234 >/dev/null; then echo "❌ Port 1234 occupied. Kill existing process first." exit 1 fi

这能提前拦截 80% 的启动失败。

4.3 Claude Code 插件连接失败:从配置到网络的全链路诊断

Claude Code for VS Code插件报错error: claude native binary not installed或Connection refused,90% 的情况与 OpenRig 无关,而是插件自身配置问题。分步排查清单:

步骤操作预期结果失败对策
1. 检查插件设置VS Code → Settings → Extensions → Claude Code →Claude: Api Base Url必须填http://localhost:3000/v1(OpenRig 网关地址)删除插件重装,避免旧配置残留
2. 验证网关健康浏览器访问http://localhost:3000/health返回{"status":"ok",...}检查npm start是否运行,端口是否被占
3. 测试网关代理curl -X POST http://localhost:3000/v1/chat/completions -H "X-Model-Target: lmstudio" -d '{"model":"llama-2","messages":[{"role":"user","content":"hi"}]}'返回模型响应 JSON检查 tmux 中 LMStudio 窗格是否有Server started on http://0.0.0.0:1234日志
4. 检查 CORS浏览器开发者工具 → Network → 查看请求的Response Headers必须包含Access-Control-Allow-Origin: *或指定域名修改server.js中cors配置,重启网关
5. 插件权限VS Code → Command Palette →Developer: Toggle Developer Tools→ Console无CORS或Network Error报错关闭所有安全插件(如 uBlock Origin),或在插件设置中启用Allow Insecure Connections

关键提醒:Claude Code 插件默认尝试连接https://api.anthropic.com,必须手动修改Api Base Url为你的 OpenRig 地址,否则它永远不会走本地代理。这个设置藏得极深,是新手最大的坑。

4.4 模型响应异常:格式不一致、token 限制、流式中断的根源分析

当你看到Error: Invalid request: messages must be an array或413 Payload Too Large,这不是模型问题,而是 OpenRig 网关的请求转换逻辑缺陷。三大高频问题与修复:

  1. 消息数组格式错误:
    Claude SDK 发送{"messages": [{"role":"user","content":"..."}]},但 Ollama 期望{"messages": [{"role":"user","content":"..."}]}结构相同,却因字段名大小写或嵌套层级不同失败。修复:在onProxyReq中添加严格校验:

    if (req.url.includes('/chat/completions')) { const body = JSON.parse(req.body.toString()); // 强制标准化 messages 格式 const standardizedMessages = body.messages.map(m => ({ role: m.role.toLowerCase(), // 确保 role 是小写 content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content) })); proxyReq.write(JSON.stringify({ model: body.model, messages: standardizedMessages })); }
  2. Token 限制触发 413 错误:
    LMStudio 默认最大上下文为 4096,但请求体可能超限。解决方案不是增大服务器限制,而是前端截断:在网关中添加中间件:

    app.use('/v1/chat/completions', (req, res, next) => { const body = req.body; if (body.messages && body.messages.length > 10) { // 仅保留最近 10 轮对话,避免 token 溢出 body.messages = body.messages.slice(-10); } req.body = body; next(); });
  3. 流式响应中断:
    text/event-stream响应在代理时容易被缓冲。http-proxy-middleware默认启用buffer,需禁用:

    app.use(`/v1`, createProxyMiddleware({ ...routeConfig, buffer: false, // 关键!禁用缓冲,保持流式传输 changeOrigin: true, secure: false }));

最后一个经验:所有模型响应问题,先用curl直连后端(如curl http://localhost:1234/v1/chat/completions),确认后端正常后再查网关。90% 的“模型问题”其实是网关配置问题。

5. OpenRig 的演进:从本地网关到团队协作平台的自然延伸

OpenRig 的本质不是软件,而是方法论。当你已经能稳定运行npm run dev启动三服务、用tmux attach查看日志、通过X-Model-Target切换模型,你就掌握了本地 AI 工作流的核心范式。下一步的演进,不是寻找一个叫 openrig 的终极解决方案,而是基于现有架构做增量增强:

  • 配置中心化:将MODEL_ROUTES从代码中抽离到config/models.yaml,用js-yaml加载,实现配置热更新;
  • 模型市场集成:在网关中添加/models/list端点,自动扫描models/目录下的 GGUF 文件,返回可用模型列表,VS Code 插件可动态下

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

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

立即咨询