使用 vLLM 和 LiteLLM 在本地 LLM 上运行 Claude Code
Source: Dev.to
请提供您希望翻译的具体文本内容(除代码块和 URL 之外),我将按照要求保持原有的 Markdown 格式和技术术语,将其翻译成简体中文。
在本地使用 vLLM + LiteLLM 运行 Claude Code
目标: 将专有源代码保留在本地,同时仍使用 Claude Code 的工作流。
解决方案: 通过 LiteLLM 代理 Claude Code 的 Anthropic Messages API 调用,将其转换为本地 vLLM 推理服务器使用的兼容 OpenAI 的 API。
Claude Code → LiteLLM (port 4000) → vLLM (port 8000) → 本地 GPU
1. 单行环境变量
export ANTHROPIC_BASE_URL="http://localhost:4000"
Claude Code 现在指向 LiteLLM 代理,而不是 Anthropic 的云端端点。
2. 模型与硬件
- 模型:
Qwen3‑Coder‑30B‑A3B‑Instruct‑AWQ(Mixture‑of‑Experts,30 B 总量,前向时激活 3 B) - GPU: 双 AMD MI60(ROCm)使用张量并行(规模 = 2)
- 量化: AWQ → 在 GPU 内存中轻松容纳
2.1 vLLM Docker 服务(docker‑compose 片段)
services:
vllm:
image: nalanzeyu/vllm-gfx906:v0.11.2-rocm6.3
container_name: vllm
devices:
- /dev/kfd:/dev/kfd
- /dev/dri/card1:/dev/dri/card1
- /dev/dri/card2:/dev/dri/card2
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/renderD129:/dev/dri/renderD129
shm_size: 16g
environment:
- HIP_VISIBLE_DEVICES=0,1
command:
- python
- -m
- vllm.entrypoints.openai.api_server
- --model
- QuantTrio/Qwen3-Coder-30B-A3B-Instruct-AWQ
- --tensor-parallel-size
- "2"
- --max-model-len
- "65536"
- --gpu-memory-utilization
- "0.9"
- --enable-auto-tool-choice
- --tool-call-parser
- qwen3_coder
为什么要使用最后两个标志?
--enable-auto-tool-choice– 让模型自行决定何时发出工具调用。--tool-call-parser qwen3_coder– 将 Qwen 的 XML 风格工具调用转换为 LiteLLM(最终由 Claude Code 使用)所期望的 OpenAI 工具调用格式。
3. LiteLLM 配置
model_list:
- model_name: claude-*
litellm_params:
model: hosted_vllm/QuantTrio/Qwen3-Coder-30B-A3B-Instruct-AWQ
api_base: http://vllm:8000/v1
api_key: "not-needed"
model_info:
max_tokens: 65536
max_input_tokens: 57344
max_output_tokens: 8192
litellm_settings:
drop_params: true # ignore Anthropic‑only params
request_timeout: 600
modify_params: true # adapt params for OpenAI API
general_settings:
disable_key_check: true # no API key needed locally
设置说明
| 设置 | 效果 |
|---|---|
drop_params: true | 静默丢弃没有 OpenAI 对应字段的 Anthropic‑特定参数。 |
modify_params: true | 允许 LiteLLM 重写参数(例如 max_tokens),以符合目标 API 的期望。 |
disable_key_check: true | 跳过 API‑密钥验证——在本地服务器无需身份验证时非常有用。 |
4. 在本地堆栈上运行 Claude Code
export ANTHROPIC_BASE_URL="http://localhost:4000"
cd my-project
claude # launches Claude Code as usual
结果: 与托管的 Anthropic API 完全相同的用户体验,但所有推理均在本地完成。
性能与限制
| 指标 | 观察 |
|---|---|
| 吞吐量 | 在双 MI60 上约 25‑30 tokens / s,首 token 延迟约 175 ms |
| 上下文窗口 | 限制为 64 K tokens(Claude Opus 可达 200 K) |
| 模型能力 | Qwen3‑Coder 在编码方面表现出色;Claude 具备更广泛的通用知识和指令遵循能力。 |
优势
- 零 API 成本
- 完整的数据主权(代码永不离开您的网络)
- 可在 air‑gapped 环境中运行
Source: …
5. 端到端测试:构建 Flask Todo 应用
export ANTHROPIC_BASE_URL="http://localhost:4000"
cd /tmp && mkdir flask-test && cd flask-test
claude --dangerously-skip-permissions -p \
"Build a Flask todo app with SQLite persistence, \
modern UI with gradients and animations, \
mobile responsive design, and full CRUD operations."
生成的项目结构
flask_todo_app/
├── app.py # Flask 路由 + SQLite 设置
├── requirements.txt # 依赖
├── run_app.sh # 启动脚本
├── static/
│ ├── css/
│ │ └── style.css # 渐变、动画、悬停效果
│ └── js/
│ └── script.js # 客户端交互
└── templates/
└── index.html # Jinja2 模板(响应式布局)
示例 app.py
from flask import Flask, render_template, request, redirect, url_for
import sqlite3
app = Flask(__name__)
def init_db():
conn = sqlite3.connect('todos.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS todos
(id INTEGER PRIMARY KEY AUTOINCREMENT,
task TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE)''')
conn.commit()
conn.close()
init_db()
@app.route('/')
def index():
conn = sqlite3.connect('todos.db')
c = conn.cursor()
c.execute('SELECT id, task, completed FROM todos ORDER BY id DESC')
todos = c.fetchall()
conn.close()
return render_template('index.html', todos=todos)
示例 CSS (static/css/style.css)
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #667eea, #764ba2);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
.header {
text-align: center;
padding: 40px 0;
color: white;
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
运行应用
cd flask_todo_app
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.py # 在 http://localhost:5000 启动 Flask
现在你可以添加、切换和删除任务;SQLite 数据库会在重启后保持持久化。
6. TL;DR
- 将
ANTHROPIC_BASE_URL设置为指向 LiteLLM 代理 (http://localhost:4000)。 - 运行 vLLM(Docker)并使用 Qwen3‑Coder 模型,添加
--enable-auto-tool-choice+--tool-call-parser qwen3_coder参数。 - 配置 LiteLLM 将所有
claude-*模型名称映射到本地 vLLM 端点。 - 像往常一样启动 Claude Code——它现在会调用您本地的 GPU,实现零成本、主权化的推理,同时保留完整的 Claude Code 工作流(包括工具调用)。
享受安全、高性能的编码辅助,永不将您的专有代码发送到外部!
生成概览
- 生成过程大约耗时五分钟,经历了多轮代理迭代。
- 每个文件都是一次独立的工具调用:模型生成代码,Claude Code 执行,返回结果,模型再规划下一步。
- 91 % 的前缀缓存命中率表明 vLLM 在多轮循环中高效复用上下文。
这证明了代理工作流能够正常运行。模型读取提示,规划文件结构,发出创建目录和写入文件的工具调用,并生成可运行的应用。所有推理都在本地的 MI60 上完成——没有代码离开我的网络。
限制与未来工作
- 规模 – 未在更大的代码库上测试。一个小的 Flask 应用算是一个案例,数千行的重构则是另一回事。
- 上下文窗口 – 64 K token 限制最终会成为瓶颈,模型在处理复杂架构决策时可能不如真实的 Claude 那样从容。
- 当前适用性 – 适合聚焦、范围明确的任务。
Claude Code 兼容性检查清单
| 要求 | 细节 |
|---|---|
| 强工具使用 | 模型必须可靠地发出结构化的工具调用 |
| 代码聚焦 | Qwen3‑Coder 表现良好;DeepSeek Coder 和 CodeLlama 系列也应可行 |
| 足够的上下文 | 我使用了 64 K;更小的窗口可能可用,但尚未测试 |
观察
- Qwen3‑Coder‑30B‑A3B 能很好地处理直接的编码任务。
- 对于复杂的重构或架构决策,真实的 Claude API 仍是更好的选择。
硬件建议
- 如果没有 64 GB 显存,可以考虑 Qwen2.5‑Coder‑7B 或 Qwen3‑8B,它们可以在单块 16 GB 或 24 GB 显卡上运行。
- 这些配置我尚未测试,无法评论它们的上下文限制或在 Claude Code 代理工作流中的表现。
工作流建议
- 与其使用宽泛的 “重构此模块” 提示,不如将工作拆分为更紧凑、聚焦的请求。
- 更细分的、范围更小的提示更能发挥小模型的优势。
完整的 Docker‑Compose 配置
services:
vllm:
image: nalanzeyu/vllm-gfx906:v0.11.2-rocm6.3
container_name: vllm
restart: unless-stopped
ports:
- "8000:8000"
devices:
- /dev/kfd:/dev/kfd
- /dev/dri/card1:/dev/dri/card1
- /dev/dri/card2:/dev/dri/card2
- /dev/dri/renderD128:/dev/dri/renderD128
- /dev/dri/renderD129:/dev/dri/renderD129
group_add:
- "44"
- "992"
shm_size: 16g
volumes:
- /mnt/cache/huggingface:/root/.cache/huggingface:rw
environment:
- HIP_VISIBLE_DEVICES=0,1
command:
- python
- -m
- vllm.entrypoints.openai.api_server
- --model
- QuantTrio/Qwen3-Coder-30B-A3B-Instruct-AWQ
- --tensor-parallel-size
- "2"
- --max-model-len
- "65536"
- --gpu-memory-utilization
- "0.9"
- --host
- "0.0.0.0"
- --port
- "8000"
- --enable-auto-tool-choice
- --tool-call-parser
- qwen3_coder
litellm:
image: litellm/litellm:v1.80.15-stable
container_name: litellm
restart: unless-stopped
ports:
- "4000:4000"
volumes:
- ./litellm-config.yaml:/app/config.yaml:ro
command:
- --config
- /app/config.yaml
- --port
- "4000"
- --host
- "0.0.0.0"
depends_on:
- vllm
运行堆栈
# Start (using nerdctl or Docker)
nerdctl compose -f coder.yaml up -d
在网络中的任意机器上,将 Claude Code 指向 Feynman(GPU 工作站),即可进行本地推理。
# When finished, tear it down
nerdctl compose -f coder.yaml down
最后思考
- 该设置并不能取代所有人的 Claude API。
- 如果需要最大能力,Anthropic 的托管模型仍是最佳选择。
- 对于在乎数据主权的人来说,本地推理意味着专有代码永不离开网络。
- 每次向 Claude Code 提问时看到自己的 GPU 亮起,也是一件令人满足的事。