Featured image of post 如何优雅的让Claude Code使用第三方模型?

如何优雅的让Claude Code使用第三方模型?

最近Claude Code爆火,很多人都说Cursor不香了。无奈原生的Claude Code使用对国人来说特别不便,我这里尝试了一些新的解决方案,希望对你流畅使用Claude Code有帮助。

背景

Claude模型的母公司Anthropic,对国内用户使用限制特别多,我曾经注册或购买的几个号没多久就阵亡了。但人家的这个工具确实不错,我们没账号怎么办?

听说可以使用一些第三方模型了,比如最近国内月之暗面推出的Kimi-K2,它们机智的直接支持了Anthropic的API。我们可以简单配置一下,就可以在Claude Code中使用Kimi-K2模型了。 但是有时我们想使用其他更强大的模型,比如Gemini,怎么办?

我又继续寻找到了最近刚开源的一个解决方案,claude-code-router,它支持了多个模型,包括Gemini,DeepSeek,GPT等。这里又产生一个问题,可以使用原生Gemini模型,但Google家模型不能精确控制预算,哪天你哐哐用,金钱也哗哗出的时候,看到账单傻眼了怎么办?

以上各个问题,本文都会尝试给一个解决方案,如果对你有帮助,请帮我点个赞吧!

本文假定你会Claude Code的安装和使用,我们直接进入主题:如何优雅的让Claude Code使用第三方模型?

初步试水:借助kimi-k2使用第三方模型

这块已经有不少文章介绍了,我简单说几个关键点:

  1. 设置两个环境变量:
1
2
export ANTHROPIC_API_KEY=`<你的API KEY>`
export ANTHROPIC_BASE_URL=https://api.moonshot.cn/anthropic
  1. 修改Claude Code的配置 ~/.claude.json 添加(你可能要先启动一次才会自动生成这个配置):
1
"hasCompletedOnboarding": true,

然后重启Claude Code,就可以使用Kimi-K2模型了。在里面似乎kimi做得足够兼容,你连模型都不用切换,直接就开箱即用了。我问了一句你是谁,看来Claude Code有被骗到:)

1
2
3
> 你是哪个模型

⏺ 我是 Claude Code,由 Anthropic 开发的官方 CLI 工具。我使用的是 Claude Sonnet 4 模型(具体版本 ID 是 claude-sonnet-4-20250514)。

kimi-k2

  1. 如果想更流畅使用,你可能至少需要充50元,不然那个限频等,体验应该会很差。

我感觉Kimi-K2这次挺“鸡贼”的,借了一波Claude Code的东风,应该引了不少新进,现在它官网开始提示繁忙起来了呢:)

我试着用了一阵Kimi-K2,有时候反应较慢,我在想是否可能把Gemini家的和OpenAI家的模型一起集成进来呢?方法当然是有的。

进阶集成:使用claude-code-router扩展你的模型库

在一两周前,我在寻找如何让Claude Code可使用更多种第三方模型。在搜索这个问题的解法,国外的Perplexity居然没有推荐这个项目,反倒是国内腾讯元宝给我介绍了有这样一个开源项目,claude-code-router(以下简称CCR)可能解决我的问题,一看到我甚为惊喜,我想莫不是这个项目是国人写的原因,咱离自己人更近。

A powerful tool to route Claude Code requests to different models and customize any request.

基本原理

在GitHub仓库中也写了项目的实现原理。简单的说,作者经过逆向分析后,发现在Claude Code中它在调用模型时,各个参数都是通过环境变量获取的,作者想到开发一个中间件,将各个环境变量替换掉,这样可以实现调用第三方模型。同时因为Claude Code使用Anthropic API的规范,我们需要将对第三方模型的调用转换成Anthropic API的格式。

安装

Claude Code类似通过npm即可安装。

1
2
3
4
5
# 安装
npm install -g @musistudio/claude-code-router

# 通过ccr启动claude code
ccr code

配置

你可以参考官方提供的示例,配置~/.claude-code-router/config.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
  "APIKEY": "your-secret-key",
  "PROXY_URL": "http://127.0.0.1:7890",
  "LOG": true,
  "Providers": [
    {
      "name": "openrouter",
      "api_base_url": "https://openrouter.ai/api/v1/chat/completions",
      "api_key": "sk-xxx",
      "models": [
        "google/gemini-2.5-pro-preview",
        "anthropic/claude-sonnet-4",
        "anthropic/claude-3.5-sonnet"
      ],
      "transformer": { "use": ["openrouter"] }
    },
    {
      "name": "deepseek",
      "api_base_url": "https://api.deepseek.com/chat/completions",
      "api_key": "sk-xxx",
      "models": ["deepseek-chat", "deepseek-reasoner"],
      "transformer": {
        "use": ["deepseek"],
        "deepseek-chat": { "use": ["tooluse"] }
      }
    },
    {
      "name": "ollama",
      "api_base_url": "http://localhost:11434/v1/chat/completions",
      "api_key": "ollama",
      "models": ["qwen2.5-coder:latest"]
    },
       {
      "name": "gemini",
      "api_base_url": "https://generativelanguage.googleapis.com/v1beta/models/",
      "api_key": "",
      "models": ["gemini-2.5-flash", "gemini-2.5-pro", "gemini-2.5-flash-lite-preview-06-17"],
      "transformer": {
        "use": ["gemini"]
      }
    },
    {
      "name": "kimi",
      "api_base_url": "https://api.moonshot.cn/v1/chat/completions",
      "api_key": "",
      "models": [
        "kimi-k2-0711-preview"
      ],
      "transformer": {
        "use": [
          "cleancache"
        ]
      }
    },
  ],
  "Router": {
    "default": "deepseek,deepseek-chat",
    "background": "ollama,qwen2.5-coder:latest",
    "think": "deepseek,deepseek-reasoner",
    "longContext": "openrouter,google/gemini-2.5-pro-preview"
  }
}

这里定义了不同的Provider,并且有一些模型可以有其设置。比如为了让DeepSeek模型更积极使用工具,有个tooluse的设置。比如为了转换Gemini模型,有个gemini的Transformer。 同时可看到,它还真是国人开发,很有本地化特色,比如显式支持PROXY设置方便你访问某些模型。

到这里配置好后,当你在使用Claude Code时,想切换模型时,可以输入/model命令,然后选择你想要的模型。比如: 在Claude Code Router中使用Kimi-K2

不过有点遗憾的是,当前通过CCR中还不支持Web搜索和图片上传,这离我们想要的完整体还是有点距离,但官方已经在计划中,并且这个项目最近更新很频繁,Star也涨得非常快。

折腾到这里就结束了吗?这里发生了一件小事,让我觉得有必要继续折腾一下。我使用OpenRouter来调用Claude模型,为了省钱,我已经很勤俭地只用 claude-3.7-sonnet 了,但几轮对话下来,发现账单还是有点夸张。我在一个不算太大的项目中进行了/init和简要对话而已。虽然OpenRouter提供了对每个KEY的费用限制(Credit limit),但是如Google的Gemini等模型,它就没有可以限制额度,那就只能等收到账单才后知后觉了?

问题不大,我想起来之前折腾过LiteLLM,它不仅能聚合LLM接口,还能像个贴心管家一样帮你控制预算。就决定是你了,继续折腾!

终极控制:使用LiteLLM统一LLM及控制支出

很早前想写一篇LiteLLM+Librechat的教程,但一直没时间,今天就让LiteLLM先出场吧。我继续在k8s中部署它,如果你是容器或其它方式,请参考官方文档,部署过程都是简单的。

配置LiteLLM

我们创建一个configmap定义了LiteLLM的配置文件config.yaml,大概内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: v1
kind: ConfigMap
metadata:
  name: litellm-config
  namespace: ai
data:
  config.yaml: |
    # LiteLLM配置
    model_list:
      # 添加Anthropic模型
      - model_name: "openrouter/anthropic/claude-3.7-sonnet"
        litellm_params:
          model: "openrouter/anthropic/claude-3.7-sonnet"
          api_key: os.environ/OPENROUTER_API_KEY
      - model_name: "openrouter/openai/gpt-4.1"
        litellm_params:
          model: "openrouter/openai/gpt-4.1"
          api_key: os.environ/OPENROUTER_API_KEY
      - model_name: "gemini/gemini-2.5-flash"
        litellm_params:
          model: "gemini/gemini-2.5-flash"
          api_key: os.environ/GEMINI_API_KEY

    # 服务器配置
    server_settings:
      port: 4000
      environment: production
      cors_allow_origins: ["*"]
      prometheus_metrics: true

    litellm_settings:
      # check_provider_endpoint: true # 👈 Enable checking provider endpoint for wildcard models
      # 禁用guardrails相关功能
      enable_guardrails: false
      enable_guardrails_in_db: false

部署LiteLLM

接着定义一个Deployment即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
apiVersion: apps/v1
kind: Deployment
metadata:
  name: litellm
  namespace: ai
spec:
  selector:
    matchLabels:
      app: litellm
  replicas: 1
  template:
    metadata:
      labels:
        app: litellm
    spec:
      volumes:
        - name: config-volume
          configMap:
            name: litellm-config
      nodeSelector:
        kubernetes.io/hostname: models
      containers:
        - name: litellm
          image: ghcr.io/berriai/litellm:v1.74.0-stable
          args:
            - "--config=/app/config.yaml"
          volumeMounts:
            - name: config-volume
              mountPath: /app/config.yaml
              subPath: config.yaml
          env:
            - name: TZ
              value: "Asia/Shanghai"
            - name: DISABLE_SCHEMA_UPDATE
              value: "true"
            - name: LITELLM_LOG
              value: "DEBUG"
            - name: DATABASE_URL
              value: "postgresql://root:admin@postgresql.base-system.svc.cluster.local:5432/litellm"
            - name: LITELLM_SALT_KEY
              value: "xxxx"
            - name: STORE_MODEL_IN_DB
              value: "True"
            - name: OPENAI_API_KEY
              value: "xxxx"
            - name: AZURE_API_KEY
              value: "xxxx"
            - name: GEMINI_API_KEY
              value: "xxxx"
            - name: DEEPSEEK_API_KEY
              value: "xxxx"
            - name: OPENROUTER_API_KEY
              value: "xxxx"
            - name: HTTP_PROXY
              value: "<your proxy>"
            - name: HTTPS_PROXY
              value: "<your proxy>"
            - name: NO_PROXY
              value: "localhost,127.0.0.1,postgresql.base-system.svc.cluster.local,postgresql,10.43.140.217"
          ports:
            - containerPort: 4000
          livenessProbe:
            httpGet:
              path: /health/liveliness
              port: 4000
            initialDelaySeconds: 40
            periodSeconds: 30
            timeoutSeconds: 10
            failureThreshold: 3
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
  name: litellm
  namespace: ai
spec:
  selector:
    app: litellm
  ports:
    - protocol: TCP
      port: 4000
      targetPort: 4000
  type: ClusterIP

要注意LiteLLM启动时,有时资源消耗会比较高,我的弱鸡k8s节点时不时会给搞得濒死,最好像上面限制一下资源。 我们可以测试一下LiteLLM对外的接口是否正常,比如:

1
2
3
4
5
6
7
curl https://litellm.mysite.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LITELLM_KEY" \
  -d '{
    "model": "gemini-2.5-flash",
    "messages": [{"role": "user", "content": "What is the capital of France?"}]
  }'

正常返回后,说明我们的LiteLLM服务工作正常。接下来我们就可以在claude-code-router中统一使用litellm作为唯一的Provider了。

在claude-code-router中使用litellm

现在,我们的config.json可以变得非常清爽,Providers里只留下litellm一个就行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "Providers": [
    {
      "name": "litellm",
      "api_base_url": "https://litellm.mysite.com/v1/chat/completions",
      "api_key": "xxxx",
      "models": [ "deepseek/deepseek-chat","deepseek/deepseek-reasoner","moonshot/kimi-k2-0711-preview","gemini/gemini-2.5-flash-lite", "gemini/gemini-2.5-flash", "openrouter/google/gemini-2.5-flash","azure/gpt-4.1", "gemini/gemini-2.5-pro","openrouter/anthropic/claude-3.7-sonnet"],
      "transformer": {
        "deepseek/deepseek-chat": { "use": ["maxtoken", { "max_tokens": 8192 }] },
        "gemini/gemini-2.5-flash-lite": { "use": ["cleancache"] },
        "gemini/gemini-2.5-flash": { "use": ["cleancache"] },
        "moonshot/kimi-k2-0711-preview": { "use": ["cleancache"] }
      }
    }
  ],
  "Router": {
    "default": "litellm,moonshot/kimi-k2-0711-preview",
    "background": "litellm,deepseek/deepseek-chat",
    "think": "litellm,deepseek/deepseek-reasoner",
    "longContext": "litellm,gemini/gemini-2.5-pro"
  }
}

这里要注意,如果直接对接官方的Gemini模型,只需要配置Gemini的Transformer即可。但这里咱们是通过LiteLLM调用的,还需要配置use: cleancache的Transformer。不然会报类似下面这样的错误:

⎿ API Error: 400 {“error”:{“message”:“Error from provider: {"error":{"message":"litellm.BadRequestError: VertexAIException BadRequestError - {\n \"error\": {\n \"code\": 400,\n \"message\": \"* GenerateContentRequest.contents: contents is not specified\\n\",\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n. Received Model Group=gemini/gemini-2.5-pro\nAvailable Model Group Fallbacks=None","type":null,"param":null,"code":"400"}}”,“type”:“api_error”,“code”:“provider_response_error”}}

还好LiteLLM的日志相当给力,我通过排查请求体,很快就定位到问题出在 “cache_control” 这个字段上——删掉它就一切正常了。最后我们可以在LiteLLM的管理端看到每次Claude Code发出了哪些请求,使用了多少Token,花费了多少钱等。 LiteLLM管理端

我们也可以在LiteLLM中创建的API_KEY中定义它的额度,这样避免我们不小心超支。 LiteLLM API_KEY额度

现在,让我们开心的在Claude Code中使用各种模型吧!

总结

本文介绍了三种方式让你更好的基于第三方大语言模型来使用Claude Code,希望对你有所帮助。我们除了直接使用Kimi-K2外,还可以使用CCR来扩展模型库,最后通过LiteLLM来统一LLM的调用,这样也能让我们更精细化的观察Token的使用以及控制费用。

三种方案对比:

特性方案一:Kimi 直连方案二:CCR方案三:CCR + LiteLLM
设置简易度⭐⭐⭐⭐⭐ (极简)⭐⭐⭐⭐ (简单)⭐⭐ (较复杂)
模型丰富度⭐ (仅 Kimi)⭐⭐⭐⭐ (丰富)⭐⭐⭐⭐⭐ (最丰富)
费用控制力⭐⭐ (依赖 Kimi 平台)⭐⭐ (依赖上游)⭐⭐⭐⭐⭐ (精准控制)
折腾系数⭐⭐⭐⭐⭐⭐⭐⭐

以上便是最近关于Claude Code的一点折腾经验,希望对你有帮助。欢迎点赞、收藏、分享,更欢迎分享你的使用经验。我们下篇文章见。

我是个爱折腾技术的工程师,也乐于分享。欢迎点赞、关注、分享,更欢迎一起探讨技术问题,共同学习,共同进步。为了获得更及时的文章推送,欢迎关注我的公众号:爱折腾的风

扫码关注公众号