手记

通过 vLLM 和 LiteLLM 在本地 LLM 上运行 Claude Code

每次使用 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 转换层

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 资源被有效利用,也能带来独特的技术满足感。

0人推荐
随时随地看视频
慕课网APP