每次使用 Claude Code 进行查询,都意味着要将源代码发送到 Anthropic 的服务器。对于专有代码库而言,这种做法是不可接受的。借助 vLLM 和 LiteLLM,我可以将 Claude Code 定向到自己的硬件——在保持相同工作流程的同时,确保代码始终保留在本地网络中。
架构设计技术实现的关键在于,Claude Code 期望使用 Anthropic Messages API,而本地推理服务器通常采用 OpenAI 的 API 格式。LiteLLM 在此起到了桥梁作用,能够接收 Anthropic 格式的请求,并将其转换为适用于本地 vLLM 实例的 OpenAI 格式。
整体技术栈如下所示:
Claude Code → LiteLLM (端口 4000) → vLLM (端口 8000) → 本地 GPU
只需设置一个环境变量即可实现该功能:
export ANTHROPIC_BASE_URL="http://localhost:4000"
配置后,Claude Code 会将所有请求发送至本地 LiteLLM 代理,再由该代理转发至运行特定模型的 vLLM 服务。
vLLM 配置当前运行的是 Qwen3-Coder 30B A3B 模型,这是一个混合专家模型,总参数量为 300 亿,但每次前向传播仅激活约 30 亿参数。通过 AWQ 量化技术降低内存需求后,可以使用张量并行将模型拆分到双 MI60 GPU 上运行:
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 参数对于实现工具调用功能至关重要,使模型能够生成 Claude Code 所期望的工具调用格式。
LiteLLM 负责将 Claude 模型名称映射到本地 vLLM 端点。通过通配符模式可以匹配 Claude Code 请求的任何模型:
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
request_timeout: 600
modify_params: true
general_settings:
disable_key_check: true
关键配置说明:
drop_params: true静默忽略无法转换为 OpenAI 格式的 Anthropic 特定参数modify_params: true允许 LiteLLM 根据目标 API 需求调整参数disable_key_check: true跳过 API 密钥验证,适用于本地环境
完成所有配置后,Claude Code 即可正常使用:
export ANTHROPIC_BASE_URL="http://localhost:4000"
cd my-project
claude
使用体验与原生 Anthropic API 基本一致,但需注意以下差异:
- 令牌吞吐量:双 MI60 配置可实现约 25-30 tokens/秒的处理速度,首次令牌响应时间约 175 毫秒
- 上下文限制:最大支持 64K 令牌,而 Claude Opus 可处理 200K 上下文
- 模型能力:Qwen3-Coder 在编码任务上表现优异,但 Claude 在知识广度和指令遵循方面更具优势
该方案的优势显而易见:零 API 成本、完整的数据主权,并且能够在隔离网络上运行 Claude Code。
工具调用模式下的文件创建真正检验 Claude Code 兼容性的标准不是简单的聊天功能,而是模型能否创建文件、执行命令并在代码库上进行迭代。--tool-call-parser qwen3_coder 参数负责处理 Qwen 的 XML 风格工具调用与 LiteLLM 期望的 OpenAI 工具格式之间的转换。
为验证端到端功能完整性,我要求 Claude Code 构建一个完整的 Flask 应用程序:
export ANTHROPIC_BASE_URL="http://localhost:4000"
cd /tmp && mkdir flask-test && cd flask-test
claude --dangerously-skip-permissions -p \
"构建一个具有 SQLite 持久化的 Flask 待办事项应用,\
包含渐变和动画的现代 UI、移动端响应式设计以及完整的 CRUD 操作"
模型成功创建了完整的项目结构:
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 包含完整的 SQLite 初始化逻辑:
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 样式表包含了渐变、玻璃拟态效果和动画实现:
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
source venv/bin/activate
python app.py
# 访问 http://localhost:5000
完整生成过程涉及多次工具调用迭代,总计耗时约五分钟。每个文件创建都是一个独立的工具调用:模型生成代码,Claude Code 执行操作,返回结果后模型继续规划后续步骤。91% 的前缀缓存命中率表明 vLLM 在多轮交互中高效地重用了上下文信息。
这证实了工具调用工作流程的功能完整性。模型能够正确解析提示词,规划文件结构,通过工具调用创建目录和文件,最终生成可正常运行的应用程序。所有推理过程均在 MI60 GPU 上本地完成,确保代码不会离开本地网络。
模型选择建议为实现 Claude Code 兼容性,建议选择具备以下特性的模型:
- 强大的工具调用能力:模型必须能够可靠地生成结构化工具调用
- 代码专注度:Qwen3-Coder 表现良好,DeepSeek Coder 和 CodeLlama 变体也应具备可行性
- 充足的上下文长度:建议使用 64K 上下文,更小的上下文窗口尚未经过充分测试
测试结果表明,Qwen3-Coder-30B-A3B 能够很好地处理常规编码任务。对于复杂的重构或架构决策,原生的 Claude API 仍然是更优选择。
如果 VRAM 容量不足(低于 64GB),可以考虑 Qwen2.5-Coder-7B 或 Qwen3-8B 等较小模型,这些模型通常可在单张 16GB 或 24GB 显卡上运行。不过这些配置的上下文限制和处理 Claude Code 工具调用工作流程的能力尚未经过验证。
无论如何调整,关键是要优化工作流程:将宽泛的"重构此模块"类提示分解为多个针对性更强的具体请求。使用更多针对性强的提示可以更好地发挥较小模型的优势。
完整技术栈部署完整配置集中在一个 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
使用 nerdctl(或 docker)启动服务:
nerdctl compose -f coder.yaml up -d
网络内的任何机器均可将 Claude Code 指向 GPU 工作站(代号 Feynman)以获得本地推理能力。使用完毕后,可通过以下命令停止服务:
nerdctl compose -f coder.yaml down
总结评估
此方案并不适合所有用户替代 Claude API。若需要最强大的模型能力,Anthropic 的托管服务仍是最佳选择。但对于重视代码隐私和安全的用户而言,本地推理提供了完全的数据主权保障,确保专有代码始终不会离开本地网络。此外,每次向 Claude Code 提问时亲眼见证自有 GPU 资源被有效利用,也能带来独特的技术满足感。