LiteLLM 部署与使用
环境:
192.168.110.207:4000用途:统一 OpenAI 兼容网关,转发到 vLLM(对话)与 Xinference(向量)
进阶:密钥 / 路由 / Fallback / 成本 / 指标 → LiteLLM 高级功能与用法
HTML:
docs/html_cursor/LiteLLM部署_cursor.html
1. 访问信息
| 项 | 值 |
|---|---|
| Base URL | http://192.168.110.207:4000 |
| Master Key | sk-litellm-bocheng-207(patches_cursor/LiteLLM部署/.env) |
| 对话模型 | qwen3.6-27b(别名 qwen、学习示例 demo-chat) |
| 向量模型 | bge-m3 |
| 学习:负载均衡 | demo-lb(自动选机);钉机别名 demo-lb-a / demo-lb-b(上游为模拟端口,调用会失败属预期) |
| 上游对话 | http://116.62.10.183:8000/v1(vLLM) |
| 上游向量 | http://192.168.110.207:9997/v1(Xinference) |
2. 一键部署 / 验收
在 Windows 项目根:
python scripts_cursor/00_部署_workbuddy到207.py
python scripts_cursor/LiteLLM部署/LiteLLM_01_部署.py
python scripts_cursor/LiteLLM部署/LiteLLM_02_验收.py207 本机也可:
bash /opt/workbuddy/scripts_bash_cursor/LiteLLM部署/LiteLLM_01_部署.sh3. 调用示例
列模型
curl -s http://192.168.110.207:4000/v1/models \
-H "Authorization: Bearer sk-litellm-bocheng-207"对话
curl -s http://192.168.110.207:4000/v1/chat/completions \
-H "Authorization: Bearer sk-litellm-bocheng-207" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.6-27b",
"messages": [{"role": "user", "content": "你好"}],
"max_tokens": 128
}'向量
curl -s http://192.168.110.207:4000/v1/embeddings \
-H "Authorization: Bearer sk-litellm-bocheng-207" \
-H "Content-Type: application/json" \
-d '{"model":"bge-m3","input":"测试文本"}'Python(OpenAI SDK)
from openai import OpenAI
client = OpenAI(
api_key="sk-litellm-bocheng-207",
base_url="http://192.168.110.207:4000/v1",
)
print(client.chat.completions.create(
model="qwen3.6-27b",
messages=[{"role": "user", "content": "你好"}],
max_tokens=64,
).choices[0].message.content)4. 如何新增一个可用模型(学习步骤)
源头文件:patches_cursor/LiteLLM部署/config.yaml 运行时文件:/opt/litellm/config.yaml
步骤
- 在
model_list:下增加一段(示例已加demo-chat):
- model_name: demo-chat # 客户端调用名
litellm_params:
model: openai/qwen3.6-27b # openai/ + 上游真实模型 id
api_base: http://116.62.10.183:8000/v1
api_key: "123456"
timeout: 300
extra_body:
chat_template_kwargs:
enable_thinking: false- 同步到 207 并重启:
# Windows 项目根
python scripts_cursor/00_部署_workbuddy到207.py
# 拷贝到运行目录并重启(或跑 LiteLLM_01_部署.py)207 上也可:
cp /opt/workbuddy/patches_cursor/LiteLLM部署/config.yaml /opt/litellm/config.yaml
sed -i 's#http://host.docker.internal:9997/v1#http://127.0.0.1:9997/v1#g' /opt/litellm/config.yaml
systemctl restart litellm- 验证:
curl -s http://192.168.110.207:4000/v1/models \
-H "Authorization: Bearer sk-litellm-bocheng-207"
curl -s http://192.168.110.207:4000/v1/chat/completions \
-H "Authorization: Bearer sk-litellm-bocheng-207" \
-H "Content-Type: application/json" \
-d '{"model":"demo-chat","messages":[{"role":"user","content":"你好"}],"max_tokens":64}'/v1/models 里能看到 demo-chat,且 chat 有回复,即新增成功。
5. 配置文件位置
| 文件 | 说明 |
|---|---|
patches_cursor/LiteLLM部署/config.yaml | 模型路由(源头) |
/opt/litellm/config.yaml | 运行时配置(systemd 读这份) |
/etc/systemd/system/litellm.service | 服务单元;含 LITELLM_MASTER_KEY |
patches_cursor/LiteLLM部署/docker-compose.yml | 容器编排(备用;当前未用 Docker 跑) |
patches_cursor/LiteLLM部署/.env | LITELLM_MASTER_KEY(与 systemd 应对齐) |
| 端口 | 4000 |
改 config.yaml 后重新执行 LiteLLM_01_部署.py(或拷贝到 /opt/litellm/ 再 systemctl restart litellm)即可生效。
6. 部署方式说明
当前 207 采用 pip + systemd(因 Docker 拉 ghcr/docker.litellm.ai 不稳定):
| 项 | 值 |
|---|---|
| 服务 | systemctl status litellm |
| 虚拟环境 | /opt/litellm-venv |
| 配置 | /opt/litellm/config.yaml(从 patches_cursor/LiteLLM部署/config.yaml 同步) |
| 版本 | litellm[proxy]==1.74.15(兼容系统 Python 3.10) |
常用命令:
systemctl status litellm
journalctl -u litellm -n 80 --no-pager
systemctl restart litellm改模型路由后:同步 config.yaml 到 /opt/litellm/ 再 systemctl restart litellm。
7. 排错
| 现象 | 处理 |
|---|---|
| chat 超时 / 502 | 检查 183 vLLM:curl -H "Authorization: Bearer 123456" http://116.62.10.183:8000/v1/models |
chat content 为空但有 reasoning_content | Qwen3 thinking 占满 token;配置已默认 enable_thinking: false,或加大 max_tokens |
| embeddings 失败 | 检查 Xinference:curl -H "Authorization: Bearer xf-..." http://127.0.0.1:9997/v1/models |
| 401 | 确认 Header 使用 Bearer sk-litellm-bocheng-207 |
| 服务挂了 | journalctl -u litellm -n 100 --no-pager |
8. 学习案例问答(Master Key / 路由 / Xinference / 负载均衡)
以下按「提出问题 → 详细回答」整理,便于对照 config.yaml 与 curl 实操。
案例 1:sk-litellm-bocheng-207 是什么?怎么定义 / 生成?
问题:这串 Key 是什么?怎么来的?
回答:它是 LiteLLM Proxy 的 Master Key(管理员级 API Key),用来校验「谁可以调用 :4000 网关」。不是算法自动生成的,而是部署时人手写死的共享口令。命名只是方便记:sk-(OpenAI 风格)+ litellm + bocheng + 207。
定义链路:
- 环境变量(真正生效):
LITELLM_MASTER_KEY=sk-litellm-bocheng-207
- 仓库:
patches_cursor/LiteLLM部署/.env - 运行:
/etc/systemd/system/litellm.service里Environment=LITELLM_MASTER_KEY=...
config.yaml引用环境变量,不直接写死字符串:
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY若要自己换一把(示例生成方式,任选其一):
openssl rand -hex 24
# 或
python -c "import secrets; print('sk-' + secrets.token_urlsafe(24))"改 .env + systemd 的 LITELLM_MASTER_KEY 后执行:
systemctl daemon-reload
systemctl restart litellm所有客户端 Bearer 也要一起改。
和上游 Key 别混:
| Key | 给谁用 | 例子 |
|---|---|---|
| Master Key | 客户端 → LiteLLM(:4000) | sk-litellm-bocheng-207 |
| 上游 api_key | LiteLLM → vLLM / Xinference | 123456、xf-... |
案例 2:现有的 Master Key 在哪里查看?
问题:已经配好的那把 Key,我去哪看?
回答(任选一处核对即可,值应一致):
| 位置 | 说明 |
|---|---|
patches_cursor/LiteLLM部署/.env | 源头:LITELLM_MASTER_KEY=... |
/etc/systemd/system/litellm.service | 运行中的环境变量 |
scripts_cursor/_config.py | 脚本常量 LITELLM_MASTER_KEY |
| 本文档 §1 访问信息表 | 文档备份 |
查看 systemd:
cat /etc/systemd/system/litellm.service
# 关注:Environment=LITELLM_MASTER_KEY=sk-litellm-bocheng-207案例 3:systemd 里定义好之后,所有接口都用这把 Key 吗?
问题:litellm.service 里写了 LITELLM_MASTER_KEY,是不是调 LiteLLM 所有接口都带它?
回答:对,在当前部署方式下(未单独建虚拟 Key),客户端调 LiteLLM(:4000)的鉴权就是这把 Master Key:
Authorization: Bearer sk-litellm-bocheng-207适用于 /v1/chat/completions、/v1/embeddings、/v1/models 等。
注意:
- 这是进网关的钥匙,不是上游的;vLLM / Xinference 的 Key 写在
model_list各条的api_key里,由 LiteLLM 代填。 - 以后若在 LiteLLM UI/库里新建虚拟 Key,那些也能当 Bearer;Master Key 始终是最高权限那把。现在没有虚拟 Key,就只有这一把。
典型 service 片段:
[Service]
Environment=LITELLM_MASTER_KEY=sk-litellm-bocheng-207
WorkingDirectory=/opt/litellm
ExecStart=/opt/litellm-venv/bin/litellm --config /opt/litellm/config.yaml --port 4000 --host 0.0.0.0案例 4:Xinference 完整 curl 有哪些?头从哪里来?
问题:直连 Xinference 时,请求长什么样?Header 从哪获取?
回答:直连 :9997,只用 Xinference API Key(xf-...),与 LiteLLM 的 sk-... 无关。
| 项 | 值 | 来源 |
|---|---|---|
| 地址 | http://192.168.110.207:9997(本机可用 127.0.0.1:9997) | 容器端口映射 |
| Key | xf-K8H3LiS27H4188XdOyWJj74MWMOlIR9tZbiybDbxbSas7eAI | Xinference 创建;仓库 scripts_cursor/_config.py 的 XF_KEY;LiteLLM config.yaml 里 bge-m3 的 api_key |
Authorization | Bearer <xf-...> | 同上,需自己抄进 curl |
Content-Type | application/json | POST 时自己写,不是接口下发的 |
列模型:
curl -s http://192.168.110.207:9997/v1/models \
-H "Authorization: Bearer xf-K8H3LiS27H4188XdOyWJj74MWMOlIR9tZbiybDbxbSas7eAI"Embedding(bge-m3):
curl -s http://192.168.110.207:9997/v1/embeddings \
-H "Authorization: Bearer xf-K8H3LiS27H4188XdOyWJj74MWMOlIR9tZbiybDbxbSas7eAI" \
-H "Content-Type: application/json" \
-d '{"model":"bge-m3","input":"测试文本"}'Rerank(bge-reranker-v2-m3):
curl -s http://192.168.110.207:9997/v1/rerank \
-H "Authorization: Bearer xf-K8H3LiS27H4188XdOyWJj74MWMOlIR9tZbiybDbxbSas7eAI" \
-H "Content-Type: application/json" \
-d '{
"model": "bge-reranker-v2-m3",
"query": "加班费怎么算",
"documents": ["加班费按300%计算", "今天天气不错"]
}'头没有「自动下发接口」可抄:Key 在 Xinference 管理端创建后记在配置里;model 名来自 GET /v1/models 或 launch 时的 -u。
案例 5:走 LiteLLM 时,还要不要带 xf-...?
问题:xf-... 已写在 config.yaml 里,那 embeddings 的 curl 是否只带 sk-litellm-... 即可?
回答:对。走 LiteLLM(:4000)时:
- 客户端只需带 Master Key:
sk-litellm-bocheng-207 xf-...不用带;LiteLLM 按bge-m3那条的api_base/api_key自己去调 Xinference
调用链:
你的 curl → LiteLLM(验 master key)→ Xinference(用 config 里的 xf- key)curl -s http://192.168.110.207:4000/v1/embeddings \
-H "Authorization: Bearer sk-litellm-bocheng-207" \
-H "Content-Type: application/json" \
-d '{"model":"bge-m3","input":"测试文本"}'案例 6:config 里很多条,只写一把 sk-...,怎么对应上某一条?
问题:model_list 有多条,鉴权又只有一把 Master Key,它怎么知道走哪条上游?
回答:靠的不是 Key 对应某一条,而是请求体里的 model 字段。
- 鉴权:Bearer Master Key → 证明能进门(所有已配置模型共用)。
- 路由:JSON 里
"model":"xxx"→ 在model_list找model_name == xxx→ 用那条的api_base/api_key打上游。
客户端 model | 命中配置 | 上游 |
|---|---|---|
bge-m3 | model_name: bge-m3 | Xinference + xf-... |
demo-chat | model_name: demo-chat | vLLM + 123456 |
demo-lb | 同名多条 | 由 router 在多台里选 |
Key 管“能不能进门”,model 管“进门后走哪条配置”。 写错或不存在的模型名会报找不到模型,与 Key 无关。
案例 7:所有 model_name 必须全局唯一吗?
问题:配置里每个 model_name 能不能重复?
回答:不一定。
| 情况 | 含义 |
|---|---|
| 每个名字一条(日常默认) | qwen、demo-chat、bge-m3 各走自己的上游,最清晰 |
同一个 model_name 多条 | 当成同一逻辑模型的多台部署 → 负载均衡 / 故障切换 |
想当不同接口用 → 名字要不同。 想同一名字打多台机器 → 故意写成同一个 model_name。
案例 8:同名多机负载均衡——真实配置形态(可模拟)
问题:同一名字打多台机器怎么写?
回答:config.yaml 里已加学习示例(上游端口故意不存在,调用失败属预期,只演示形态)。核心:
# ① 自动负载均衡:同名两条 → 客户端 model=demo-lb
- model_name: demo-lb
litellm_params:
model: openai/fake-qwen-a
api_base: http://127.0.0.1:18001/v1
api_key: "fake-key-machine-a"
timeout: 10
max_retries: 0
- model_name: demo-lb
litellm_params:
model: openai/fake-qwen-b
api_base: http://127.0.0.1:18002/v1
api_key: "fake-key-machine-b"
timeout: 10
max_retries: 0
router_settings:
routing_strategy: simple-shuffle # 随机选一台客户端只写一个逻辑名:
curl -s http://192.168.110.207:4000/v1/chat/completions \
-H "Authorization: Bearer sk-litellm-bocheng-207" \
-H "Content-Type: application/json" \
-d '{"model":"demo-lb","messages":[{"role":"user","content":"hi"}],"max_tokens":16}'/v1/models 对外只显示 一个 demo-lb(逻辑名去重);配置里却是两条部署。生产把两个 api_base 换成两台真实 vLLM 即可。
完整片段见:patches_cursor/LiteLLM部署/config.yaml(含下方钉机别名)。
案例 9:可以手动指定是哪一台吗?
问题:负载均衡很好用,但排障时能否钉死某一台?
回答:可以。最实用做法是:均衡名 + 唯一别名钉机(同一台既参与 demo-lb,又单独挂 demo-lb-a / demo-lb-b)。
客户端 model | 行为 |
|---|---|
demo-lb | 自动负载均衡,在 A/B 里由 simple-shuffle 选 |
demo-lb-a | 钉死 A 机(:18001) |
demo-lb-b | 钉死 B 机(:18002) |
配置片段:
- model_name: demo-lb-a
litellm_params:
model: openai/fake-qwen-a
api_base: http://127.0.0.1:18001/v1
api_key: "fake-key-machine-a"
timeout: 10
max_retries: 0
- model_name: demo-lb-b
litellm_params:
model: openai/fake-qwen-b
api_base: http://127.0.0.1:18002/v1
api_key: "fake-key-machine-b"
timeout: 10
max_retries: 0# 自动选机
... -d '{"model":"demo-lb", ...}'
# 指定 A / B(排障、灰度、压测)
... -d '{"model":"demo-lb-a", ...}'
... -d '{"model":"demo-lb-b", ...}'LiteLLM 还有按 tag 路由等高级写法;当前场景用唯一别名钉机已够用。