利用ccproxy构建智能AI模型代理网关,无缝切换Claude Code多模型
2026/5/14 14:07:10 网站建设 项目流程

1. 项目概述

如果你和我一样,日常重度依赖 Claude Code 这样的 AI 编程助手,那你肯定也遇到过类似的困扰:手头有多个不同厂商的 AI 模型 API,比如 OpenAI 的 GPT-4o、Google 的 Gemini 2.0 Flash,甚至是一些支持联网搜索的模型,但 Claude Code 这个官方客户端却只能“死心眼”地调用 Anthropic 自家的 Claude 模型。这就像你车库里停着一辆跑车、一辆越野车和一辆皮卡,但车钥匙却只能启动其中一辆,其他车都成了摆设。更让人头疼的是,不同模型各有优劣——Claude 在代码推理上稳扎稳打,但上下文窗口有限;Gemini 的 2M 超长上下文处理大文件是神器;而需要联网搜索时,又得手动切换到 Perplexity 的网页端。这种割裂的体验,严重拖慢了开发效率。

ccproxy这个工具,就是为了解决这个痛点而生的。它本质上是一个智能的 AI 模型请求代理网关,专门为 Claude Code 这类官方客户端设计。它的核心思路非常巧妙:不是去破解或修改 Claude Code 本身,而是在你的本地电脑上启动一个“中间人”服务器。当 Claude Code 试图向 Anthropic 的官方 API 发送请求时,ccproxy会拦截这些请求,然后根据你预先设定好的规则,智能地将请求路由到最合适的模型上去处理,最后再把结果原封不动地返回给 Claude Code。对于 Claude Code 来说,它以为自己一直在和“官方服务器”对话,浑然不知背后已经完成了一次精妙的“偷梁换柱”。

这样一来,你就能实现一个近乎完美的开发工作流:日常的代码补全、解释和重构,继续交给响应快、成本低的 Claude Haiku 或 Sonnet;当遇到需要深度思考的复杂算法问题时,自动切换到能力更强的 Claude Opus;当你丢给它一个巨大的代码库文件要求分析时,请求会被自动转发给拥有超长上下文的 Gemini;而一旦对话中触发了“联网搜索”工具调用,ccproxy又能瞬间把任务交给 Perplexity 这类专精搜索的模型。所有这一切,都在一个统一的 Claude Code 界面中无缝完成,你无需在多个应用或标签页之间来回切换。

我最初接触这个项目时,觉得它解决了一个非常实际的工程效率问题。经过一段时间的深度使用和配置调优,我发现它不仅仅是一个简单的“转发器”,其基于规则的路由引擎和可扩展的钩子(Hooks)系统,让它可以适应各种复杂的场景。接下来,我将从设计思路、详细配置、实战调优到排错心得,为你完整拆解如何利用ccproxy打造属于你自己的全能 AI 编程伴侣。

2. 核心设计思路与架构解析

2.1 为什么是代理(Proxy)模式?

在深入配置之前,理解ccproxy为何选择代理模式至关重要。市面上让客户端使用不同模型的方法大致有三种:一是修改客户端源码,直接替换 API 端点;二是使用系统级的网络重定向工具;三是像ccproxy这样,在应用层充当代理。

修改客户端源码是最直接但也是最笨的方法。且不说 Claude Code 这类闭源软件无法修改,即使可以,每次客户端更新都可能带来兼容性问题,维护成本极高。系统级网络重定向(比如修改 Hosts 文件或使用透明代理)虽然通用,但过于“粗暴”。它无法理解 HTTP 请求包体内的具体内容(比如模型名称、思考模式标志),因此无法实现基于请求内容的智能路由。

ccproxy采用的应用层代理模式则是一个优雅的折中方案。它在本地(通常是localhost:4000)启动一个 HTTP 服务器,这个服务器完全兼容 Anthropic 的 API 接口规范。你只需要告诉 Claude Code:“别去找api.anthropic.com了,去找localhost:4000吧。” 这个本地服务器收到请求后,就有机会对完整的请求体(JSON 格式)进行解析、判断和修改,然后再代表 Claude Code 去调用真正的目标 API(可能是 Anthropic,也可能是 OpenAI 或 Google)。处理完响应后,它再将结果返回。这个过程对客户端是完全透明的。

这种模式的优势非常明显:

  1. 无侵入性:不需要改动 Claude Code 的一行代码,完全通过环境变量控制。
  2. 内容感知:可以基于 Token 数量、是否启用思考、使用了哪个工具等具体内容做出路由决策。
  3. 集中管理:所有模型的 API Key、路由规则都在一个统一的配置文件中管理,安全又方便。
  4. 灵活扩展:基于 Python 和 LiteLLM 生态,可以轻松添加自定义路由逻辑或处理钩子。

2.2 核心组件协作流程

ccproxy的流畅运行依赖于几个核心组件的紧密协作。我们可以把整个系统想象成一个高效的物流分拣中心:

  1. Claude Code(发货方):它产生原始的货物(API 请求),并打算发往固定的地址(Anthropic API)。
  2. ccproxy规则引擎(分拣规则):这是物流中心的大脑,预定义了一套分拣规则。例如:“重量大于 50kg 的货发往 A 仓库(大容量模型)”,“标有‘易碎’的货发往 B 仓库(高精度模型)”。
  3. LiteLLM 代理服务器(物流中心与运输车队):这是实际运转的中心。它接收货物,根据规则引擎贴上的标签,将货物重新打包成对应仓库(如 OpenAI、Google)要求的格式,并调用对应的运输车队(API 调用)送达。
  4. ccproxy钩子(Hooks)(特殊处理流水线):在分拣和运输过程中,可能需要进行一些特殊处理,比如给货物贴上内部追踪码(提取会话ID),或者把发货方的VIP卡(OAuth Token)一并交给运输车队。钩子就是这些特定的处理工序。

具体到一次请求的生命周期,数据流是这样的:

  • 步骤1:你在 Claude Code 中输入“请分析这个 10 万行的日志文件”。Claude Code 会构造一个包含消息内容、模型参数(比如model: claude-3-5-sonnet-20241022)和超大上下文的请求,准备发送给https://api.anthropic.com
  • 步骤2:因为你设置了ANTHROPIC_BASE_URL=http://localhost:4000,这个请求被发送到了本地运行的ccproxy(即 LiteLLM 代理服务器)。
  • 步骤3:LiteLLM 收到请求后,首先会调用ccproxy注册的rule_evaluator钩子。这个钩子就像扫描仪,读取请求内容:发现 Token 数量巨大,超过了TokenCountRule里设定的阈值(例如 60k)。于是,它给这个请求打上了一个token_count的标签。
  • 步骤4:接着,model_router钩子被触发。它查看请求上的token_count标签,然后去查阅config.yaml中的“路由表”。路由表里写着:token_count标签的请求,应该使用model_name: gemini-2.0-flash这个“别名”来处理。
  • 步骤5:LiteLLM 继续工作,它发现最终要调用的模型是gemini-2.0-flash。它在config.yaml的部署列表里找到这个别名对应的真实配置:model: gemini-2.0-flashapi_base: https://generativelanguage.googleapis.com,并且需要使用 API Key 认证。
  • 步骤6:在发送请求给 Google API 之前,forward_apikey钩子(如果配置了)会将 Claude Code 请求头中的 API Key(如果有)或从环境变量中读取的 Google API Key 添加到请求中。
  • 步骤7:LiteLLM 将重新封装好的请求发送给 Google 的 Gemini API。
  • 步骤8:Gemini API 返回流式响应。LiteLLM 接收这个响应流,并直接将其转发回 Claude Code。
  • 步骤9:Claude Code 像往常一样接收到来自“Anthropic API”的流式输出,并在界面中逐字显示结果。整个过程中,用户完全感知不到背后的模型已经切换。

这个架构的精妙之处在于解耦:规则定义(做什么判断)和模型部署(用什么服务)是分开配置的。你可以独立地调整路由策略和模型供应商,而不会影响到另一方。

3. 从零开始:安装与环境配置详解

3.1 安装方式的选择与考量

ccproxy官方推荐使用uv工具进行安装,这是有深层次原因的。uv是一个用 Rust 编写的、极其快速的 Python 包管理器和解析器。对于ccproxy这种需要与另一个复杂包(LiteLLM)紧密集成的情况,uv能确保两者被安装到同一个、隔离的 Python 环境中,从根本上避免后续令人头疼的导入错误。

如果你选择使用传统的pip安装,你必须非常小心地确保ccproxylitellm[proxy]被安装到同一个虚拟环境(Virtual Environment)中。在实际操作中,这很容易出错,特别是当你系统中有多个 Python 版本或活跃的虚拟环境时。因此,除非你对 Python 环境管理有十足的把握,否则强烈建议跟随官方推荐,使用uv

安装uv本身非常简单。如果你的系统是 macOS 且安装了 Homebrew,一行命令即可:

brew install uv

对于 Linux 或 Windows(通过 WSL),可以使用官方的安装脚本:

# 在终端中运行以下命令安装 uv curl -LsSf https://astral.sh/uv/install.sh | sh

安装完成后,重启你的终端,或者执行source ~/.bashrc(或source ~/.zshrc)来让uv命令生效。你可以通过uv --version来验证安装。

3.2 执行安装与初始化

确保uv就绪后,安装ccproxy就成了一行命令的事情:

uv tool install claude-ccproxy --with 'litellm[proxy]'

这行命令做了以下几件事:

  1. uv tool install:告诉uv要安装一个命令行工具。
  2. claude-ccproxy:这是ccproxy在 PyPI 上的包名。
  3. --with 'litellm[proxy]':这是关键。它指示uv在安装claude-ccproxy时,必须同时安装litellm包及其proxy额外依赖项。uv会智能地将它们全部安置在同一个独立的环境中。

安装过程通常很快。完成后,你可以立刻验证:

ccproxy --help

如果看到一系列可用的命令说明(如install,start,run),说明工具安装成功。接下来,你需要初始化配置文件:

ccproxy install

这个命令会在你的用户主目录下创建一个.ccproxy的隐藏文件夹(~/.ccproxy),并在里面生成两个核心的配置文件模板:ccproxy.yamlconfig.yaml。你可以用tree命令查看一下:

tree ~/.ccproxy # 预期输出: # /Users/你的用户名/.ccproxy # ├── ccproxy.yaml # 路由规则和钩子配置 # └── config.yaml # LiteLLM 模型部署配置

注意ccproxy install默认不会覆盖已存在的配置文件。如果你想把配置重置回初始状态,可以加上--force参数:ccproxy install --force。不过,在初次安装后修改配置时,我更推荐直接编辑这两个 YAML 文件,而不是重新生成。

3.3 验证环境与常见安装陷阱

安装完成后,一个重要的验证步骤是检查ccproxylitellm是否真的在同一个 Python 环境中。虽然使用uv安装大大降低了出错概率,但养成检查的习惯能帮你快速定位未来可能出现的诡异问题。

# 首先,找到 litellm 命令的实际位置 which litellm # 输出可能类似:/Users/你的用户名/.local/bin/litellm # 或者:/Users/你的用户名/Library/Application Support/uv/bin/litellm # 然后,使用该路径所在的 Python 解释器尝试导入 ccproxy # 这里用一个子shell命令来拼接路径 $(dirname $(which litellm))/python -c "import ccproxy; print(ccproxy.__file__)"

如果第二条命令成功执行,并打印出了ccproxy模块文件的路径(例如/Users/.../site-packages/ccproxy/__init__.py),那么恭喜你,环境是完美的。如果它报错ModuleNotFoundError: No module named 'ccproxy',则说明两者不在同一个环境。

遇到环境问题怎么办?这是新手最常踩的坑。如果你的系统之前用pip装过litellm,或者存在多个 Python 版本,uv安装的litellm可能没有被放在你的 Shell 路径最前面。解决方案是彻底重装,让uv强制接管:

# 首先,如果之前用 pip 安装过,可以尝试卸载(但注意别误删其他项目依赖) # pip uninstall litellm ccproxy # 使用 --force 参数强制 uv 重新安装,确保环境纯净 uv tool install claude-ccproxy --with 'litellm[proxy]' --force

安装并验证无误后,你就可以启动代理服务器了:

ccproxy start --detach

--detach参数会让服务在后台运行。你可以用ccproxy status检查服务状态,看到"status": "running"就表示代理服务器已经在localhost:4000就绪了。

4. 核心配置实战:打造智能路由策略

配置文件是ccproxy的灵魂所在。~/.ccproxy/目录下的两个 YAML 文件,一个管“怎么分”(规则),一个管“分到哪”(模型)。理解并熟练配置它们,你才能发挥出ccproxy的全部威力。

4.1 规则定义:ccproxy.yaml 深度解析

ccproxy.yaml文件定义了请求的分类规则处理流水线(钩子)。我们可以把它拆解成几个部分来看。

第一部分:基础配置与钩子流水线

ccproxy: debug: false # 生产环境建议设为 false,避免日志过于冗长 oat_sources: anthropic: "jq -r '.claudeAiOauth.accessToken' ~/.claude/.credentials.json"
  • debug: 开启后会打印非常详细的调试日志,在初次配置排查问题时非常有用,但正常使用时建议关闭。
  • oat_sources: 这是 OAuth Token 源的定义。ccproxy支持从外部命令获取 Token。例如,Claude Code 桌面端通常会将 OAuth Token 保存在~/.claude/.credentials.json文件中。上面这行配置使用jq这个命令行 JSON 处理工具,从该文件中提取出accessToken。如果你的 Claude Code 是通过其他方式登录的,可能需要调整这个路径或命令。

第二部分:钩子执行顺序

hooks: - ccproxy.hooks.rule_evaluator - ccproxy.hooks.model_router - ccproxy.hooks.forward_oauth - ccproxy.hooks.extract_session_id

hooks定义了请求被处理时,各个钩子的执行顺序。这个顺序很重要:

  1. rule_evaluator:必须先执行,因为它负责给请求打标签,后续路由依赖这个标签。
  2. model_router:根据标签,修改请求中的模型字段。
  3. forward_oauth:将 OAuth Token 添加到要转发给下游 API 的请求头中。
  4. extract_session_id:用于可观测性,比如将会话 ID 发送到 LangFuse 这类追踪平台。

你可以注释掉不需要的钩子,或者调整顺序(虽然通常不需要)。例如,如果你只用 API Key 认证,不用 OAuth,就可以注释掉forward_oauth

第三部分:路由规则集这是最核心的部分。rules是一个列表,ccproxy会按照列表顺序逐一评估每个规则,直到第一个匹配的规则为止,并为请求打上该规则的name作为标签。如果没有任何规则匹配,则标签为default

rules: - name: long_context rule: ccproxy.rules.TokenCountRule params: - threshold: 60000 # 当请求的Token数超过6万时触发 - name: web_search rule: ccproxy.rules.MatchToolRule params: - tool_name: WebSearch # 当请求中使用了名为“WebSearch”的工具时触发 - name: background_task rule: ccproxy.rules.MatchModelRule params: - model_name: claude-3-5-haiku-20241022 # 当Claude Code请求的模型是Haiku时触发 - name: deep_think rule: ccproxy.rules.ThinkingRule # 当请求启用了“思考”模式时触发

规则详解与实战场景

  • TokenCountRule(长上下文路由):这是优化成本和处理能力的利器。Claude 3.5 Sonnet 的上下文窗口是 200K,但处理长上下文消耗的资源多、速度慢、费用高。而 Gemini 2.0 Flash 拥有 2M 的上下文窗口,且处理长文本性价比极高。你可以设置一个阈值(比如 60K),当 Claude Code 发送的对话历史 Token 数超过这个值时,自动将请求路由到 Gemini。这样,日常短对话用 Claude,分析长文档时自动切换,又快又省。
  • MatchToolRule(工具调用路由):Claude Code 支持调用外部工具,比如“联网搜索”。但 Claude 本身的搜索能力可能不如 Perplexity 或 ChatGPT 的联网版。通过此规则,你可以配置当 Claude Code 尝试调用WebSearch工具时,将整个请求(包括用户的问题)路由到专精搜索的模型,获取更优质的搜索结果,再返回给 Claude Code 进行整合呈现。
  • MatchModelRule(模型指定路由):Claude Code 允许你在设置中选择默认模型(如 Sonnet)和后台任务模型(如 Haiku)。这个规则可以识别出 Claude Code 对特定模型的请求。例如,你可以将后台任务(通常是低优先级的、不需要强推理的补全任务)全部路由到更便宜的 Haiku 或 GPT-3.5 Turbo,从而节省主模型的使用额度。
  • ThinkingRule(深度思考路由):当用户在消息中要求模型“深入思考”或“逐步推理”时,Claude Code 会在请求中设置一个thinking标志。此规则能捕获该标志。你可以将这类需要深度分析的任务,路由到能力最强的模型,如 Claude Opus 或 GPT-4,以确保思考质量。

配置心得:规则顺序就是优先级顺序。把最具体、条件最严格的规则放在前面,最通用的default规则(如果有的话)放在最后。例如,web_search规则应该放在long_context前面,因为“搜索”是一个明确的动作指令,优先级高于单纯的长度判断。

4.2 模型部署与别名映射:config.yaml 详解

如果说ccproxy.yaml是“调度规则”,那么config.yaml就是“资源地图”和“运输清单”。它告诉 LiteLLM 有哪些模型可用,以及如何调用它们。

核心概念:模型别名(Alias)这是ccproxy实现灵活路由的关键。在config.yaml中,你会定义两套配置:

  1. 模型别名:这是给ccproxy的规则引擎看的“目的地标签”。例如,thinklong_contextdefault
  2. 模型部署:这是真实的、具体的 API 端点配置。例如,anthropic/claude-3-5-sonnet-20241022gemini-2.0-flash

ccproxymodel_router钩子工作时,会把请求中的model字段,从 Claude Code 指定的原始值(如claude-3-5-sonnet-20241022),替换成规则匹配后对应的别名(如think)。然后 LiteLLM 拿着这个别名(think),在config.yaml里找到同名的model_name条目,并使用该条目下的litellm_params去调用真正的 API。

下面是一个支持多厂商的实战配置示例:

model_list: # ========== 别名配置区 ========== # 这里定义的 model_name 就是 ccproxy 路由的目标标签 - model_name: default litellm_params: model: claude-sonnet # 指向下方名为 ‘claude-sonnet’ 的部署 - model_name: think litellm_params: model: claude-opus # 指向下方名为 ‘claude-opus’ 的部署 - model_name: long_context litellm_params: model: gemini-flash # 指向下方名为 ‘gemini-flash’ 的部署 - model_name: web_search litellm_params: model: perplexity-api # 指向下方名为 ‘perplexity-api’ 的部署 - model_name: background_task litellm_params: model: gpt-3.5-turbo # 指向下方名为 ‘gpt-3.5-turbo’ 的部署 # ========== 实际部署配置区 ========== # Anthropic Claude - model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_base: https://api.anthropic.com api_key: ${ANTHROPIC_API_KEY} # 从环境变量读取 - model_name: claude-opus litellm_params: model: anthropic/claude-3-5-opus-20241022 api_base: https://api.anthropic.com api_key: ${ANTHROPIC_API_KEY} - model_name: claude-haiku litellm_params: model: anthropic/claude-3-5-haiku-20241022 api_base: https://api.anthropic.com api_key: ${ANTHROPIC_API_KEY} # Google Gemini - model_name: gemini-flash litellm_params: model: gemini-2.0-flash api_base: https://generativelanguage.googleapis.com api_key: ${GEMINI_API_KEY} # OpenAI - model_name: gpt-3.5-turbo litellm_params: model: gpt-3.5-turbo api_base: https://api.openai.com/v1 api_key: ${OPENAI_API_KEY} - model_name: gpt-4o litellm_params: model: gpt-4o api_base: https://api.openai.com/v1 api_key: ${OPENAI_API_KEY} # Perplexity API (联网搜索) - model_name: perplexity-api litellm_params: model: perplexity/llama-3.1-sonar-small-128k-online api_base: https://api.perplexity.ai api_key: ${PERPLEXITY_API_KEY} litellm_settings: callbacks: - ccproxy.handler # 这是必须的,用于连接 ccproxy 的钩子系统 drop_params: true # 建议开启,丢弃请求中 LiteLLM 不支持的参数,避免错误 max_budget: 10.0 # 设置一个预算上限,防止意外消耗 general_settings: master_key: ${LITELLM_MASTER_KEY} # 可选,用于 LiteLLM 的管理员 API database_url: "sqlite:///./litellm.db" # 可选,用于记录使用日志 otel: true # 可选,开启 OpenTelemetry 追踪

配置要点与避坑指南

  1. API Key 管理:强烈建议使用环境变量(${VAR_NAME})来配置 API Key,而不是直接写在 YAML 文件里。这样更安全,也便于在不同环境(开发、生产)间切换。你需要在启动ccproxy前,在终端里导出这些变量:

    export ANTHROPIC_API_KEY="sk-ant-..." export OPENAI_API_KEY="sk-..." export GEMINI_API_KEY="AIza..." export PERPLEXITY_API_KEY="pplx-..."

    可以将这些export命令添加到你的 Shell 配置文件(如~/.zshrc)中,以便每次打开终端自动设置。

  2. 模型名称格式:LiteLLM 使用统一的provider/model-name格式来标识模型。例如,anthropic/claude-3-5-sonnet-20241022。务必查阅 LiteLLM 文档 以获取你所用服务的正确模型标识符。

  3. api_base的重要性:对于大多数主流服务(Anthropic, OpenAI, Google),api_base可以省略,LiteLLM 知道默认的端点。但对于一些特殊服务或自托管模型,必须正确配置。例如 Perplexity 的端点就是https://api.perplexity.ai

  4. 别名与部署的映射:确保model_list上半部分的“别名”区中,每个litellm_params.model的值,都能在下半部分的“部署”区找到一个完全相同的model_name。这是路由能成功的关键。

  5. 预算控制max_budget是一个重要的安全阀。设置一个你能接受的月度最大金额(如 10.0 美元),LiteLLM 会跟踪消耗,并在接近限额时拒绝请求,防止因配置错误或意外高频调用导致账单爆炸。

配置好这两个文件后,执行ccproxy stop && ccproxy start --detach重启服务,你的智能路由网关就配置完成了。

5. 高级用法与自定义扩展

5.1 使用 ccproxy run 命令启动应用

配置好代理并启动服务后,你有几种方式来让 Claude Code 使用它。最简单直接的是使用ccproxy run命令:

ccproxy run claude

这个命令会在一个临时的子进程中设置好所有必要的环境变量(主要是ANTHROPIC_BASE_URL=http://localhost:4000),然后启动 Claude Code。这种方式的好处是即用即走,不影响你终端中其他环境。

对于更频繁的使用,我推荐将环境变量设置到你的 Shell 配置中,一劳永逸。打开你的~/.zshrc~/.bashrc文件,在末尾添加:

# 设置 Claude Code 使用本地代理 export ANTHROPIC_BASE_URL="http://localhost:4000"

保存后,执行source ~/.zshrc使其生效。之后,在任何终端窗口中直接输入claude启动,它都会自动连接到你本地的ccproxy服务器。

你还可以创建一个别名,方便快速切换。比如,当你需要临时绕过代理,直接使用官方 API 时:

# 在 .zshrc 中添加 alias claude-proxy='ANTHROPIC_BASE_URL="http://localhost:4000" claude' alias claude-direct='unset ANTHROPIC_BASE_URL && claude'

这样,claude-proxy命令走代理,claude-direct命令直连官方。

5.2 自定义规则与钩子开发

ccproxy内置的规则可能无法满足你所有的奇思妙想。幸运的是,它提供了强大的扩展能力,允许你编写自定义的规则(Rule)和钩子(Hook)。

自定义规则示例:基于关键词路由假设你希望所有包含“[紧急]”前缀的消息,都使用最快的模型(比如 GPT-4o)来处理,以获得最及时的响应。你可以创建一个 Python 文件,例如~/.ccproxy/custom_rules.py

# ~/.ccproxy/custom_rules.py from typing import Dict, Any from ccproxy.rules import BaseRule class UrgentMessageRule(BaseRule): """ 自定义规则:检测消息中是否包含‘[紧急]’标签。 如果包含,则优先路由到高速模型。 """ name = "urgent" # 规则匹配后的标签名 def evaluate(self, data: Dict[str, Any]) -> bool: """ 评估函数。data 是 LiteLLM 接收到的原始请求字典。 返回 True 表示规则匹配。 """ # 从请求中获取消息列表 messages = data.get("messages", []) for message in messages: # 通常用户消息的角色是 'user',内容在 'content' 字段中 if message.get("role") == "user": content = message.get("content", "") # 检查内容是否为字符串,并判断是否包含关键词 if isinstance(content, str) and "[紧急]" in content: return True return False

然后,在你的ccproxy.yaml中引入这个自定义规则:

rules: - name: urgent # 这个 name 会覆盖 Python 类中定义的 name,但建议保持一致 rule: custom_rules.UrgentMessageRule # 注意导入路径 - name: web_search rule: ccproxy.rules.MatchToolRule params: - tool_name: WebSearch # ... 其他规则

自定义钩子示例:请求日志记录钩子可以在请求/响应的不同生命周期阶段插入自定义逻辑。例如,你想把所有经过代理的请求和响应摘要记录到一个本地文件,用于后续分析或调试。创建~/.ccproxy/custom_hooks.py

# ~/.ccproxy/custom_hooks.py import json import logging from datetime import datetime from typing import Dict, Any, Optional logger = logging.getLogger(__name__) def request_logger(data: Dict[str, Any], **kwargs) -> Optional[Dict[str, Any]]: """ 一个简单的请求日志钩子。 它在 rule_evaluator 之后、model_router 之前被调用比较合适。 """ # 提取关键信息 model_requested = data.get("model", "unknown") messages = data.get("messages", []) user_message = "" for msg in messages: if msg.get("role") == "user": # 只记录前100个字符,避免日志过大 content = msg.get("content", "") if isinstance(content, str): user_message = content[:100] + ("..." if len(content) > 100 else "") break # 记录到文件 log_entry = { "timestamp": datetime.utcnow().isoformat(), "type": "request", "model_requested": model_requested, "user_message_preview": user_message, "full_data_keys": list(data.keys()) # 不记录完整数据以保护隐私 } with open("/tmp/ccproxy_requests.log", "a") as f: f.write(json.dumps(log_entry) + "\n") # 钩子可以修改 data,也可以不修改直接返回 None # 这里我们只是记录,所以返回 None,让数据继续流动 return None

ccproxy.yaml中配置这个钩子。你需要考虑把它放在哪个位置。由于它只是记录,不依赖路由结果,可以放在靠前的位置:

hooks: - ccproxy.hooks.rule_evaluator - custom_hooks.request_logger # 我们的自定义日志钩子 - ccproxy.hooks.model_router # ... 其他钩子

开发与调试技巧

  1. 使用可编辑模式安装:在开发自定义规则/钩子时,使用uv tool install --editable . --with 'litellm[proxy]'命令在ccproxy项目目录下安装。这样你对源代码的修改会立即生效,无需重新安装包。
  2. 开启调试日志:在ccproxy.yaml中设置debug: true,并在config.yamllitellm_settings下也设置debug: true。这样可以在ccproxy logs中看到详细的请求处理流程,包括你的自定义代码被调用的日志。
  3. 注意导入路径:自定义的 Python 文件需要放在~/.ccproxy/目录下,或者在你的 Python 路径中。在ccproxy.yaml中引用时,使用文件名(不含.py后缀)作为模块名。

5.3 集成到其他开发工具链

ccproxy的价值不仅限于 Claude Code 桌面端。任何通过 Anthropic SDK 或兼容 Anthropic API 接口的工具,理论上都可以通过它进行路由。

在 Python 脚本中使用: 如果你有自己的 Python 脚本使用anthropic库,你可以通过设置环境变量来让它走ccproxy

import os import anthropic # 方法1:在代码中设置环境变量 os.environ["ANTHROPIC_BASE_URL"] = "http://localhost:4000" # 方法2:在创建客户端时指定 base_url client = anthropic.Anthropic( base_url="http://localhost:4000", api_key="your-api-key" # 这里的 key 可以是任意值,因为 ccproxy 会用自己的 OAuth 或 Key ) # 之后的调用就会经过 ccproxy 路由 response = client.messages.create( model="claude-3-5-sonnet-20241022", # 这个模型名会被 ccproxy 的规则覆盖 max_tokens=1000, messages=[{"role": "user", "content": "Hello"}] )

在 VS Code 插件或其他 IDE 中: 许多 IDE 的 AI 插件也支持自定义 API 端点。你可以在插件的设置中,将 Anthropic API 的 Base URL 设置为http://localhost:4000。这样,IDE 内的 AI 助手请求也会被ccproxy智能路由。

6. 故障排查与性能优化实录

6.1 常见问题与解决方案

即使配置正确,在实际使用中也可能遇到各种问题。以下是我在长期使用中总结的一些典型故障及其解决方法。

问题一:启动失败,报错ImportError: Could not import handler from ccproxy

  • 现象:执行ccproxy start后,进程立刻退出,查看日志显示无法导入ccproxy模块。
  • 根本原因:这是最经典的安装问题。litellm进程和ccproxy包不在同一个 Python 环境中。litellm找不到ccproxy这个模块。
  • 解决方案
    1. 确认安装方式:务必使用uv tool install并包含--with 'litellm[proxy]'
    2. 强制重装:uv tool install claude-ccproxy --with 'litellm[proxy]' --force
    3. 验证环境:按照前面“验证环境与常见安装陷阱”一节的方法,检查litellmccproxy是否在同一路径下。
    4. 检查 PATH:有时系统可能有多个litellm命令。用which -a litellm查看所有,确保排在第一位的是uv安装的那个。

问题二:Claude Code 连接超时或无响应

  • 现象:Claude Code 启动后,一直显示“连接中”或“正在思考”,然后报错超时。
  • 排查步骤
    1. 检查代理服务状态:运行ccproxy status。确保状态是running,并且urlhttp://localhost:4000
    2. 检查端口占用ccproxy默认使用 4000 端口。运行lsof -i :4000(macOS/Linux)或netstat -ano | findstr :4000(Windows)查看是否有其他进程占用。如果有,可以在ccproxy.yamllitellm:部分修改port:为其他值(如4001),并记得更新环境变量ANTHROPIC_BASE_URL
    3. 查看详细日志:运行ccproxy logs -f实时查看日志。在 Claude Code 中发送一条消息,观察日志输出。常见的错误有:
      • API Key 错误:日志中会显示401 UnauthorizedInvalid API Key。请检查config.yaml中对应模型的api_key环境变量是否已正确设置并导出。
      • 模型名称错误:日志显示Model not found。请检查config.yamlmodel字段的拼写是否正确,特别是provider/model的格式。
      • 网络连接错误:无法连接到api.anthropic.comapi.openai.com。请检查你的网络环境,确保可以访问这些外部 API。

问题三:路由规则不生效

  • 现象:明明配置了TokenCountRule,但发送长文本时并没有被路由到 Gemini。
  • 排查步骤
    1. 确认规则顺序:在ccproxy.yaml中,规则是按顺序评估的。如果有一个更通用的规则(比如MatchModelRule匹配了所有请求)放在前面,后面的TokenCountRule就不会被执行。调整规则顺序,将更具体的规则放在前面。
    2. 开启调试模式:在ccproxy.yamlconfig.yaml中都设置debug: true,然后重启服务并查看日志。日志会显示每个请求被哪个规则匹配,打上了什么标签,以及最终被路由到了哪个模型别名。这是诊断路由问题最直接的方法。
    3. 检查 Token 计算TokenCountRule依赖 LiteLLM 对 Token 的计数。确保你的请求消息格式正确。你可以暂时在自定义钩子中添加日志,打印出data字典的结构,看看messages字段是否如预期。

问题四:流式响应中断或显示不全

  • 现象:Claude Code 中回复显示到一半突然停止,或者出现乱码。
  • 可能原因与解决
    1. 网络不稳定:代理服务器、你的网络到目标 API 服务器之间的任何环节不稳定都可能导致流中断。尝试使用更稳定的网络环境。
    2. 模型响应格式问题:不同模型返回的流式数据格式可能有细微差别。确保你使用的 LiteLLM 版本与ccproxy兼容。可以尝试更新到最新版本:uv tool install claude-ccproxy --with 'litellm[proxy]' --force
    3. 缓冲区问题:在极少数情况下,可能是 LiteLLM 代理的缓冲区设置问题。可以尝试在config.yamllitellm_settings中添加stream_timeout: 600(单位秒),增加流式响应的超时时间。

6.2 性能调优与最佳实践

为了让ccproxy运行得更稳定、高效,可以考虑以下优化措施:

1. 调整 LiteLLM 工作进程数ccproxy.yamllitellm:部分,有一个num_workers参数,默认为 4。这个参数决定了 LiteLLM 服务器可以同时处理多少个请求。

  • 如果你的使用场景是单用户、顺序请求:可以将其设置为12,以减少内存占用。
  • 如果你需要同时处理多个高并发请求(例如,在团队中共享,或多个脚本同时调用),可以适当增加,比如设置为 CPU 核心数。但请注意,每个 worker 都是一个独立的 Python 进程,会增加内存消耗。可以通过ccproxy logs观察是否有请求排队现象来调整。

2. 合理设置超时与重试网络请求难免失败。在config.yaml的每个模型部署配置中,可以添加超时和重试参数,提高鲁棒性。

- model_name: claude-sonnet litellm_params: model: anthropic/claude-3-5-sonnet-20241022 api_base: https://api.anthropic.com api_key: ${ANTHROPIC_API_KEY} timeout: 300.0 # 单个请求超时时间(秒) max_retries: 2 # 失败后重试次数

3. 启用使用量追踪与预算控制特别是当你在团队中分享此代理,或者自己同时使用多个付费模型时,开启使用量追踪和预算控制至关重要。

  • 数据库记录:如上文配置示例,设置database_url: "sqlite:////path/to/litellm.db"。LiteLLM 会将每次调用的模型、Token 用量、成本估算记录到 SQLite 数据库中。你可以定期查看,分析使用模式。
  • 预算控制:设置max_budget: 50.0。当所有模型的总计费用估算超过 50 美元时,LiteLLM 将开始拒绝新的请求,直到你手动重置或提高预算。这是一个非常重要的“保险丝”。

4. 监控与告警对于生产级使用,可以考虑更深入的监控:

  • 日志聚合:将ccproxy logs的输出导向到像ELK(Elasticsearch, Logstash, Kibana)或Loki这样的日志聚合系统。
  • 健康检查:LiteLLM 代理提供了/health端点。你可以编写一个简单的定时脚本,定期访问http://localhost:4000/health,如果返回不是200 OK,则发送告警(如邮件、Slack 消息)。
  • OpenTelemetry:在general_settings中启用otel: true,并配置 OpenTelemetry 收集器,可以将链路追踪数据发送到 Jaeger 或 Tempo 等平台,可视化请求在ccproxy和各个模型 API 之间的流转路径和耗时。

5. 安全加固ccproxy运行在你本地,风险相对较低,但仍需注意:

  • Master Key:如果开启了 LiteLLM 的管理员 API(通过master_key),请确保该密钥足够复杂,并避免泄露。
  • 环境变量:永远不要将 API Key 硬编码在config.yaml中。坚持使用环境变量。
  • 网络监听:默认ccproxy监听在127.0.0.1:4000,这意味着只有本机可以访问。切勿将其改为0.0.0.0除非你完全清楚后果,并且配置了防火墙或认证,否则你的代理和 API Key 将暴露在局域网甚至公网中。

经过以上的配置、优化和排错,你的ccproxy应该已经成为一个稳定、高效且功能强大的 AI 模型路由中枢。它不仅能无缝整合你的多个 AI 资源,更能通过智能路由策略,在成本、速度和效果之间取得最佳平衡,真正让你的 Claude Code 如虎添翼。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询