LiteLLM 本地统一网关 —— 零基础配置攻略
面向:不写代码也能照着做的人 本机项目位置:
D:\Code\20261015_litellm-proxy网关地址:http://127.0.0.1:4000/v1(只在自己电脑上开放,外网访问不到) 最近更新:2026-10-15 晚 配套技术备忘录:同目录20261015 LiteLLM本地统一网关配置.md
一、这份攻略要解决什么问题
你手上现在有一大堆"AI 账号":谷歌的 Gemini、智谱的 GLM、深度求索的 DeepSeek、火山方舟、OpenRouter……
麻烦在哪?
- 每个平台都有自己的网址、自己的钥匙(API Key),换个软件就得重新填一遍。
- 某个平台今天额度用完了、或者突然抽风,软件就直接报错,你得手动去改配置换一个。
- 想知道"我这个月到底在 AI 上花了多少钱",得挨个平台登录去看。
LiteLLM 网关就是来解决这三件事的。 你可以把它理解成——
一个"总机接线员"。 所有软件都只记住总机的电话号码(
127.0.0.1:4000),只填总机的分机号(比如auto)。 至于这个电话最后是由 Gemini 接、还是由 GLM 接,由总机按你写好的顺序自动去试。 打不通第一家,它自己立刻拨第二家,你什么都不用管。
一句大白话:装一个"AI 电话总机",只填一个地址,坏了自己换,花钱有账本。
二、先搞懂 4 个词(后面全靠它们)
| 词 | 大白话解释 | 在本机对应什么 |
|---|---|---|
| 网关(Proxy) | 那个"总机"。一个转接用的中间程序 | D:\Code\20261015_litellm-proxy 这个程序,跑起来后占着 127.0.0.1:4000 这个门牌号 |
| 上游(Provider) | 真正干活的 AI 公司服务器 | Google、智谱、DeepSeek、OpenRouter、火山方舟 |
| 模型组名(别名) | 你给总机起的"分机号" | auto、auto-cn、glm-4-flash 这些名字 |
| 降级链(Fallback) | 打不通就换下一家的顺序表 | 写死在配置里的一串名单,如 A → B → C |
关键理解:软件里填的是"分机号",不是"真实模型名"。
分机号 auto 的样子是固定的,但它背后今天可能由 Gemini 接、明天由 GLM 接。
所以配置里换模型,你的软件一个字都不用改——这正是网关最大的好处。
三、这套网关给你带来的 5 个好处
- 一个地址接所有 AI。 任何支持 OpenAI 格式的软件(Cherry Studio、Chatbox、Hermes、各种插件),
网址填
http://127.0.0.1:4000/v1,钥匙填总机钥匙,模型填auto,就通了。 - 自动降级,不中断。 主模型报错(额度用完、网络不通、限流),毫秒级自动换下一家,你几乎无感。
- 钥匙集中管理。 五家平台的钥匙只存在一个地方(
~/AppData/Local/hermes/.env),软件里只有总机钥匙。 - 有账本。 每条请求花了多少 token、多少钱,都记进
spend.db,可出报表。 - 完全私有。 只在
127.0.0.1(本机)监听,没有对外端口,别人连不上,也不会把你的对话内容上传到第三方。
四、动手之前:先认清这台机器上的 5 个文件
都在 D:\Code\20261015_litellm-proxy\ 目录里:
| 文件 | 作用 | 能不能手改? |
|---|---|---|
build_config.py |
配置的"唯一源头"。所有模型、降级顺序都写在这里 | ✅ 要改配置就改它 |
config.yaml |
程序真正读的配置。由上面那个脚本自动生成 | ❌ 千万别手改,下次重建会被覆盖 |
client.env |
存"总机钥匙"(网关自己的密码)和总机网址 | 一般不用动 |
spend.db |
账本(SQLite 数据库文件) | 不用动,用报表工具看 |
proxy.log |
网关的运行日志,出问题先看它 | 只看不改 |
⚠️ 第一条铁律:只改
build_config.py,不要手改config.yaml。 这条规则最容易犯。config.yaml第一行就写着"自动生成,勿手改"。 手改一时爽,下次一重建(重启前必做的动作)就全没了,然后你会怀疑人生。
上游那五家的钥匙存在另一个地方:C:\Users\<你的用户名>\AppData\Local\hermes\.env。
build_config.py 会自动去那里读,所以钥匙不会出现在 config.yaml 之外的地方被人看到。
五、日常操作:只要记住 3 条命令
打开终端(本机用的是 Git-Bash 风格的命令行),先进入项目目录:
cd /d/Code/20261015_litellm-proxy
1. 启动网关
双击 start_proxy.bat 也可以,命令行方式如下:
.venv/Scripts/litellm.exe --config config.yaml --host 127.0.0.1 --port 4000 > proxy.log 2>&1
注意:这条命令会一直占住窗口不返回,这是正常的(网关是个常驻程序)。
所以要么用双击 start_proxy.bat,要么在终端里让它在后台跑。
2. 看它活了没有(最常用)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4000/health/liveliness
- 显示
200= 活着,正常。 - 显示
000或者报错 = 没起来,去看proxy.log最后 20 行。
3. 关掉它
PID=$(netstat -ano | grep -E ':4000\s+.*LISTENING' | head -1 | awk '{print $NF}'); taskkill //F //PID $PID
为什么要写得这么绕?因为直接找"litellm"这个程序名去杀杀不干净—— 它启动后会变成两个进程(一个包装进程 + 一个真正干活的),只杀一个会留下 "僵尸网关":端口不占了,但进程还在,于是你重启了配置却像没生效。 所以按端口占用者去杀才准。
改配置之后的完整流程(三步,缺一不可)
cd /d/Code/20261015_litellm-proxy
# ① 重建配置(从 .env 读钥匙,重新生成 config.yaml)
.venv/Scripts/python.exe build_config.py
# ② 结构体检(有没有写错的模型名、有没有绕成死循环)
.venv/Scripts/python.exe validate_config.py
# ③ 杀掉旧的 + 启动新的
PID=$(netstat -ano | grep -E ':4000\s+.*LISTENING' | head -1 | awk '{print $NF}'); taskkill //F //PID $PID
# 然后双击 start_proxy.bat
六、这台机器现在的"路由表"(谁优先、谁接替)
6.1 分机号(你在软件里填的名字)
| 分机号 | 第一跳(起步模型) | 用完了自动往哪走 | 什么时候用它 |
|---|---|---|---|
auto |
OpenCode Go 订阅的 deepseek-v4.1-flash |
订阅内免费模型 → 官方免费 Gemini → GLM-4.7-flash → glm-4-flash → glm-4.5-flash → DeepSeek → 本地模型 | 默认就用这个 |
auto-fast |
官方 gemini-3.1-flash-lite(最快) |
GLM 系 | 想要"秒回"、不太在意质量 |
auto-strong |
订阅的 deepseek-v4.1-flash(超时放宽到 5 分钟) |
glm-z1-flash(推理)→ DeepSeek-Pro | 难题、长文分析 |
auto-cn |
GLM-4.7-flash | glm-4-flash → 本地模型 | 外网整个断了时手动换它,全程国内直连 |
ds41-flash |
订阅的 deepseek-v4.1-flash |
订阅内免费模型 → 官方 Gemini → GLM | 只想用订阅额度、不想绕路 |
ocf-catjam |
订阅内的免费模型 cat-jam | 官方 Gemini → GLM | 最快(实测 0.8 秒)、免费 |
glm-4-flash |
GLM-4-flash | glm-4.5-flash → DeepSeek | 图便宜、图稳定 |
local-qwen |
本机 llama.cpp | (终点) | 断网、断钱,纯离线 |
一句话记法:平时填 auto,外网断了改 auto-cn。
6.2 真正的降级顺序(auto 的完整链路)
① OpenCode Go 订阅 deepseek-v4.1-flash ← 订阅主力(月额度 $80,实测 1.6~3.7 秒)
↓ 额度用尽 / 429 / 超时 / 连不上
② 订阅内免费模型 longcat-2.5-preview-free ← 免费、不限量(实测 3.3~6.4 秒)
↓
③ 订阅内免费模型 cat-jam-free ← 免费、不限量(实测 0.8~2.0 秒)
↓
④ 官方 gemini-3-flash-preview ← 免费层:20 次/天
↓
⑤ 官方 gemini-3.6-flash ← 免费层:20 次/天
↓
⑥ 官方 gemini-3.5-flash ← 免费层:20 次/天
↓
⑦ 官方 gemini-3.1-flash-lite ← 免费层:20 次/天
↓
⑧ GLM-4.7-flash(国内直连) ← 免费,偶发"访问量过大"
↓
⑨ glm-4-flash → glm-4.5-flash(国内直连) ← 免费
↓
⑩ ds-flash(DeepSeek 官方)
↓
⑪ local-qwen(本机模型,完全离线) ← 终点
关于"优先 Gemini"的实话(这一条已经过时,但原理仍值得知道):
官方 Gemini 免费层是 每款模型每天 20 次(不是每分钟 20 次!)。
API 报错原文写得很清楚:Quota exceeded ... limit: 20 ... Please retry in 11h9m。
所以它只能当"第四顺位之后的免费补位",不适合当主力。
关于"订阅额度用尽后走免费版"的实话(重要):
订阅里确实有一个 deepseek-v4.1-flash-free,但它用不了。实测请求它会被拒绝:
403 FreeTierError:OpenCode's free tier can only be used from within OpenCode.
翻译:免费层只允许在 OpenCode 自己的客户端里用,别的程序(包括本网关)一律拒绝。 我们试过把身份伪装成 OpenCode 也没用(服务端不是看这个),而且它压根不在订阅端点的模型清单里。 所以第二顺位改成了同在订阅内、实测可用的免费模型(第②③跳那两个), 效果一样:主力额度用完后自动落到不花钱的模型,你不需要做任何事。
6.3 已停用的"花钱模型"
OpenRouter 上那些按量计费的模型(Claude、GPT、以及同款 Gemini 的付费通道),
2026-10-15 已全部从网关里摘掉,理由是你要求的"只走免费链路"。
它们在 build_config.py 里以注释形式留着(搜 or-claude 就能看到),
哪天想重新启用,把注释去掉、填上 OpenRouter 钥匙、把名字加回降级链即可。
七、怎么查"刚才那条请求到底是谁回答的"
这是最实用的技能。网关有个账本 spend.db。看最近 20 条:
cd /d/Code/20261015_litellm-proxy
.venv/Scripts/python.exe -c "
import sqlite3
c = sqlite3.connect('spend.db')
for r in c.execute('select id,ts,model,prompt_tokens,completion_tokens,status from spend_log order by id desc limit 20'):
print(r)
"
怎么看:
status = failure的行,就是"第一优先尝试失败"的那一跳。- 紧跟在它后面的
status = success行,就是实际回答你的模型。 - 典型样子长这样(这就是"降级成功"的铁证):
(263, '2026-10-15T21:04:58', 'gemini-3.1-flash-lite', 23284, 4, 'success') ← 实际是它答的
(261, '2026-10-15T21:04:10', 'gemini-3-flash-preview', 0, 0, 'failure') ← 首选的官方 preview 429 了
看花费报表:
.venv/Scripts/python.exe spend_report.py --days 7 # 按模型汇总
.venv/Scripts/python.exe spend_report.py --days 7 --detail # 明细
⚠️ 一个容易误会的点:免费模型也会显示"花了多少钱"。 账本里的金额是 LiteLLM 按"官方标价"估算的参考值,不是真实扣款。 官方免费层被计成
$0.0058这种数字,实际 Google 一分钱没扣。 判断真花钱要看有没有走 OpenRouter 付费通道——现在那些通道已经全关了,所以真实花费是 0。
八、常见问题急救手册
Q1. 软件报"连接被拒绝 / Connection refused"
网关没起来。三步排查:
1. curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4000/health/liveliness → 不是 200 就是没起来。
2. tail -20 proxy.log 看最后的报错。
3. 最常见原因是端口 4000 被另一个进程占着(比如上一轮的僵尸进程)。
用第五章"关掉它"的命令杀干净,再启动。
Q2. 明明是 35 个模型,怎么现在只有 29 个?
不是坏了。2026-10-15 把 OpenRouter 的 7 个付费模型停用了(or-*),
所以从 35 变 29。这是故意的,为了只走免费链路。
Q3. 为什么我明明配了 Gemini 优先,实际全走 GLM?
先查额度,不要先怀疑配置。 顺序:
1. 查账本(第七章),看 failure 行的错误。
2. 直接给 Google 发一个最小请求看原始报错:
- HTTP 400 模型不存在 → 名字写错了
- HTTP 429 limit: 20 ... retry in 11h → 每天 20 次的额度用完了(当前最常见)
- HTTP 429 该模型当前访问量过大 → 瞬时过载,等一下就好
3. 结论话术要诚实:"降级链工作正常" ≠ "首选模型在工作"。
免费额度下首选经常不是主力,这是额度的限制,不是配置的错。
Q4. 有时候一条回复要等 14 秒、甚至 45 秒?
降级链只在"报错"时触发,它感知不到"慢但成功"。
一个模型排队 20 秒才回 200,网关只能原样把结果交给你。
这类尖峰是某个上游(尤其 GLM-4.7-flash 高峰期)在排队,不是网关的开销。
实测基线:auto 中位 1.1 秒、auto-cn 中位 1.3 秒;偶发 14~45 秒是上游排队。
想避免就改用 glm-4-flash(实测 0.4 秒)或 auto-fast。
Q5. 报错里出现 429,是什么意思?
429 = "请求太多了 / 额度用完了",不是"你配置写错了"。
网关的处理方式是:立刻换下一家(不做无谓重试,因为重试只会让你多等一遍退避时间)。
实测这个决定把最坏等待从 60.9 秒压到了 3.1 秒。
Q6. 改了配置,重启了,但感觉没生效?
99% 是僵尸进程。litellm.exe 启动后会派生出两个 python 进程,
只杀父进程会留下不占端口但仍在运行的"幽灵",它还在用旧配置。
按第五章的命令(按端口占用者杀 + 复查)处理。
Q7. 网关重启后,软件里的钥匙全失效了?
不该发生。总机钥匙存在 client.env 里,首次生成后会一直复用。
如果真失效了,看 client.env 里的 OPENAI_API_KEY 是否被清空。
Q8. 重启电脑之后还要手动启动吗?
不用。已经配了"登录自启":
- D:\Code\20261015_litellm-proxy\autostart.vbs 是启动逻辑(已在运行就跳过,不会起两个)。
- …\Start Menu\Programs\Startup\litellm-gateway.vbs 是自启入口。
- autostart.log 是启动记录,出现 already running, skip 就是幂等护栏生效。
想撤销自启:把启动目录里那个 litellm-gateway.vbs 删掉即可(纯用户级,不用管理员)。
Q9. 报错说 Request is missing x-opencode-session 是什么意思?
这是 OpenCode Go 的硬性要求:请求必须带一个"会话标识"头,不带就拒绝。 不是你的钥匙或配置错了。
- 从网关发出:已经在
build_config.py里加好了extra_headers,正常不会有这个问题。 - 从 Hermes 直接发出:本机 Hermes 版本旧、不会自动带,
已在
config.yaml的model.default_headers里补上(见第十章)。 - 症状就是"被后备链接管、订阅额度没用上",看到这条报错就照第十章检查。
Q10. 订阅的免费模型(longcat / cat-jam)回复很慢或者返回空内容?
两个已知点:
1. 这几个免费模型先"思考"再回答。如果你把「最大输出长度」设得很小
(比如 32),额度会被思考过程吃光,正文就是空的。把上限调到 300 以上就正常了。
2. 它们是"限时免费/预览"模型,延迟会波动(实测 cat-jam 0.8 秒,longcat 3~6 秒)。
嫌慢就手动把模型改成 ocf-catjam。
九、把这台总机接给别的软件
任何支持"OpenAI 兼容接口"的软件都一样,三个填空:
| 填空项 | 填什么 |
|---|---|
| 接口地址 / Base URL | http://127.0.0.1:4000/v1 |
| API Key / 密钥 | 打开 D:\Code\20261015_litellm-proxy\client.env,抄里面 OPENAI_API_KEY= 后面那串 |
| 模型 / Model | auto(或第六章表格里任意一个分机号) |
举例(Cherry Studio):设置 → 模型服务 → 添加"OpenAI",按上表填三格,点测试连接,能通就够了。
十、接给 Hermes(本机 AI 助手)—— 已经配好了
Hermes 这边现在是"三层保险":
| 层 | 设置 | 作用 |
|---|---|---|
| 主力 | 模型 = OpenCode Go 订阅的 deepseek-v4.1-flash |
直连吃订阅额度(月 $80) |
| 后备① | 本地网关 litellm-local 的 auto |
订阅额度用尽 / 报错时立刻切进来,走订阅内免费模型 → 官方 Gemini → GLM |
| 后备② | DeepSeek deepseek-v4-flash |
连网关进程都挂了的最后兜底 |
真机验证日志(关键那一行):
22:19:30 OpenAI client created provider=opencode-go base_url=https://opencode.ai/zen/go/v1 model=deepseek-v4.1-flash
22:19:47 API call #1: model=deepseek-v4.1-flash provider=opencode-go in=22789 out=4 latency=17.6s
没有任何 400、没有触发降级 → 订阅的模型真正被用上了。
⚠ 一个必须知道的技术细节:x-opencode-session
OpenCode Go 有个硬性要求:每个请求必须带一个叫 x-opencode-session 的"会话标识"头,
不带就直接拒绝(报错原文:Request is missing x-opencode-session and cannot be routed efficiently)。
本机 Hermes 版本较旧(0.17.0),不会自动带这个头,结果就是:每次请求都被拒 → 后备链接管 → 订阅额度一点都没用上。表现为"明明配好了却走了别的模型"。
已在 config.yaml 的 model: 下补上(这是 Hermes 官方支持的配置项):
model:
provider: opencode-go
default: deepseek-v4.1-flash
default_headers:
x-opencode-session: hermes-cli-opencode-go # 补上必需的头
User-Agent: hermes-agent/0.17.0 # 官方也要求用自有 UA 而非 SDK 默认名
副作用:这个 ID 是固定值,而官方建议"每个会话一个"。功能完全正常, 只是提示词缓存的优化效果会略打折扣。想彻底解决需要升级 Hermes(官方新版本已内建发送)。
还有一条细节值得知道:遇到 429 之后,Hermes 会把主力模型冷冻 60 秒, 这段时间内不会再去敲那扇已经关上的门,避免每条消息都白等一次。
配置存在 C:\Users\<你的用户名>\AppData\Local\hermes\config.yaml。
⚠️ 这份文件有 700 多行、注释很多,不要用记事本直接改、也不要用"读进来再整体写回"的脚本改
(会把注释和钥匙一起弄坏)。要改请让 Hermes 用"文本锚点替换"的方式改。
十一、名词小词典
| 名词 | 大白话 |
|---|---|
| LiteLLM | 一个开源程序,作用就是当"AI 总机"。它自己不是 AI,只是转接员 |
| Proxy / 代理 | 站在你和 AI 公司中间帮忙转发的程序 |
| API Key | 就是各家的"钥匙",泄露了别人就能用你的额度 |
| token | AI 眼里的"字数单位"。中文大约 1 个字 ≈ 1 个 token 上下,英文约 4 个字母 1 个 token |
| 429 | 服务端说"你请求太多 / 额度没了" |
| fallback / 降级 | 第一家不行就换第二家 |
| cooldown / 冷却 | 某家刚失败,先冷冻一小段时间不再去试它,免得每次请求都白等 |
| health / liveliness | 网关的"我在活着吗"检查接口,返回 200 就是活着 |
| .env | 专门存钥匙的文件,和其他配置分开放 |
| SQLite / spend.db | 一个"单文件小数据库",这里是账本 |
十二、一页速查卡
# 进入项目
cd /d/Code/20261015_litellm-proxy
# 启动(或直接双击 start_proxy.bat)
.venv/Scripts/litellm.exe --config config.yaml --host 127.0.0.1 --port 4000 > proxy.log 2>&1
# 健康检查(200 = 活着)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:4000/health/liveliness
# 停止(按端口占用者杀,避免僵尸)
PID=$(netstat -ano | grep -E ':4000\s+.*LISTENING' | head -1 | awk '{print $NF}'); taskkill //F //PID $PID
# 改配置三步:重建 → 体检 → 重启
.venv/Scripts/python.exe build_config.py
.venv/Scripts/python.exe validate_config.py
# 然后重新启动
# 全量测试 / 模拟断网测试 / 计费验证
.venv/Scripts/python.exe test_all.py
.venv/Scripts/python.exe test_fallback.py
.venv/Scripts/python.exe verify_spend.py
# 花费报表
.venv/Scripts/python.exe spend_report.py --days 7
.venv/Scripts/python.exe spend_report.py --days 7 --detail
软件里的三个填空: 地址 http://127.0.0.1:4000/v1 | 钥匙看 client.env | 模型写 auto
十三、三条最容易踩的坑(血泪总结)
- 不要手改
config.yaml。 它是自动生成物,下次重建直接覆盖你的修改。 要改就改build_config.py,然后跑重建。 - 启动必须用
.venv\Scripts\litellm.exe,不要用python -m litellm。 后者会报No module named litellm.__main__—— 这是包装机制决定的,不是环境坏了。 - 别用"重启了却没生效"来怀疑人生。 先查有没有僵尸进程(按端口杀,不要按名字杀)。 这个坑解释过至少三次"配置明明改了却没用"的假象。
本攻略由 Hermes 于 2026-10-15 依据本机实测写成,所有命令均在 D:\Code\20261015_litellm-proxy 上真机验证通过。