上个月账单出来,我整个人都不好了------Claude Code 的 Token 费用翻了 4 倍。
团队 15 个人全员用上 Claude Code 之后,爽是真爽,贵也是真贵。
折腾了两周搞定了。核心思路:Claude Code 的任务不都需要强模型,简单任务分流到开源模型。实测成本降约 70%,开发者无感。
TL;DR
- Amazon SageMaker 部署 Kimi-K2.5/GLM-5 开源模型
- LiteLLM Proxy 做统一网关 + 智能路由
- 自定义 Hook 根据 Prompt 特征自动分流
- 支线任务(占 60%+)走私有化模型,主线任务走 Amazon Bedrock
- 代码不出 VPC,性价比提升约 3.2 倍
Claude Code 的任务有"主线"和"支线"
Claude Code 执行任务时不是一路调同一个模型,会自动拆两类:
主线任务------你直接提的需求:
- 代码重构、架构设计
- 复杂 bug 排查
- 技术方案评审
支线任务------Claude Code 自动触发的辅助操作:
- 会话标题生成
- Bash 命令描述
- Hook 条件评估(判断是否要启动 SubAgent)
- 下一步建议生成
我翻了一周调用日志,支线任务消耗 Token 占总量 60% 以上。输入输出格式固定、上下文短、逻辑简单,用 Claude Sonnet 纯属浪费。
架构长这样
java
开发者 → Claude Code → LiteLLM Proxy
├── 主线任务 → Amazon Bedrock (Claude Sonnet)
└── 支线任务 → Amazon SageMaker (Kimi/GLM)
LiteLLM Proxy 是统一入口,开发者不需要知道后面接了啥。一个自定义 Hook 负责根据 Prompt 特征判断任务类型,动态切换后端模型。
关于安全性:支线任务在 VPC 内处理,不出内网。主线走 Amazon Bedrock,有 VPC Endpoint 接入和 SOC2/ISO27001 认证。
动手:4 步搞定
Step 1: SageMaker 部署开源模型
推理引擎用 SGLang,原生支持 SageMaker Inference API。模型推荐 Kimi-K2.5 或 GLM-5。
bash
git clone https://github.com/ybalbert001/claude-code-aws-skills.git
cd claude-code-aws-skills/skills/sglang-deploy
python deploy.py \
--model-id kimi-k2.5 \
--instance-type ml.p5.48xlarge \
--endpoint-name kimi-endpoint \
--region us-east-1
⚠️ 踩坑预警:第一次选了
ml.g5.12xlarge,直接 OOM。大模型吃显存,实例选型宁大勿小。
Step 2: LiteLLM Proxy 配置 + 启动
config.yaml 核心配置:
yaml
general_settings:
store_model_in_db: true
master_key: "sk-your-master-key"
router_settings:
timeout: 180
litellm_settings:
callbacks:
- "stream_anthropic_schema_fixer.hook"
- "dynamic_tagging_handler.proxy_handler_instance"
model_list:
- model_name: sagemaker-kimi-2-5
litellm_params:
model: sagemaker-chat/kimi-endpoint
aws_region_name: us-east-1
timeout: 180
max_tokens: 8192
drop_params: true
- model_name: bedrock-claude-sonnet46
litellm_params:
model: bedrock/anthropic.claude-sonnet-4-6-v1:0
aws_region_name: us-west-2
timeout: 300
Docker Compose 一把启动:
yaml
services:
litellm:
image: ghcr.io/berriai/litellm:v1.82.3-stable
restart: always
volumes:
- ./config.yaml:/app/config.yaml
- ./stream_anthropic_schema_fixer.py:/app/stream_anthropic_schema_fixer.py:ro
- ./dynamic_tagging_handler.py:/app/dynamic_tagging_handler.py:ro
command:
- "--config=/app/config.yaml"
ports:
- "8080:4000"
environment:
DATABASE_URL: "postgresql://llmproxy:dbpassword9090@db:5432/litellm"
STORE_MODEL_IN_DB: "True"
ENABLE_ANTHROPIC_SCHEMA_FIX: "true"
env_file:
- .env
depends_on:
- db
db:
image: postgres:16
restart: always
environment:
POSTGRES_USER: llmproxy
POSTGRES_PASSWORD: dbpassword9090
POSTGRES_DB: litellm
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
bash
docker compose up -d
# 确认健康
curl http://localhost:8080/health
Step 3: Claude Code 连上 Proxy
一个 alias 搞定:
bash
alias cc_proxy="ANTHROPIC_API_KEY=sk-your-litellm-key \
ANTHROPIC_BASE_URL=http://your-litellm-host:8080 \
ANTHROPIC_DEFAULT_SONNET_MODEL=bedrock-claude-sonnet46 \
ANTHROPIC_DEFAULT_HAIKU_MODEL=bedrock-claude-haiku45 \
CLAUDE_CODE_SUBAGENT_MODEL=bedrock-claude-sonnet45 \
claude"
跑 cc_proxy 启动,和直连 Claude 体验一模一样。
Step 4: 动态路由 Hook(灵魂部分)
这是整套方案最关键的代码。LiteLLM 的 Callback Handler 能在 API 调用前拦截请求,根据 Prompt 特征改路由:
python
# dynamic_tagging_handler.py
from litellm.integrations.custom_logger import CustomLogger
class DynamicRoutingHandler(CustomLogger):
def log_pre_api_call(self, kwargs, response_obj, start_time, end_time):
messages = kwargs.get("messages", [])
full_text = self._extract_all_text(messages)
task_model = self._detect_task_type(full_text)
if task_model:
kwargs["model"] = task_model
return kwargs
def _extract_all_text(self, messages):
text_parts = []
for msg in messages:
content = msg.get("content", "")
if isinstance(content, str):
text_parts.append(content)
elif isinstance(content, list):
for block in content:
if block.get("type") == "text":
text_parts.append(block.get("text", ""))
return " ".join(text_parts)
def _detect_task_type(self, text):
if self._is_hook_evaluator(text):
return "sagemaker-kimi-2-5"
elif self._is_session_title(text):
return "sagemaker-kimi-2-5"
elif self._is_bash_desc(text):
return "sagemaker-kimi-2-5"
elif len(text) > 10000:
return "bedrock-claude-sonnet46"
return None
def _is_hook_evaluator(self, text):
markers = [
"You are evaluating a hook in Claude Code",
"hook condition",
"Return your evaluation as a JSON object",
'"satisfied": true'
]
return sum(1 for m in markers if m in text) >= 3
def _is_session_title(self, text):
return "Generate a short title" in text
def _is_bash_desc(self, text):
return "Describe what this bash command does" in text
proxy_handler_instance = DynamicRoutingHandler()
用多特征阈值匹配避免误判。_is_hook_evaluator 至少 3 个特征命中才路由,误判率极低。
还有个坑:Streaming Schema 不兼容
这个坑了我两天。Claude Code 流式解析器严格按 Anthropic Messages API 设计。开源模型返回数据丢字段,直接报错。
写了个 Hook 逐 chunk 补字段:
python
# stream_anthropic_schema_fixer.py
from litellm.integrations.custom_logger import CustomLogger
from typing import AsyncGenerator, Optional, Dict, Any
class AnthropicSchemaFixerHook(CustomLogger):
async def async_post_call_streaming_iterator_hook(
self, user_api_key_dict, response: AsyncGenerator,
request_data: dict
) -> AsyncGenerator:
last_usage = None
async for chunk in response:
if not isinstance(chunk, bytes):
yield chunk
continue
try:
decoded = chunk.decode("utf-8")
if not decoded.startswith("event:"):
yield chunk
continue
event_type, data_json = self._parse_sse(decoded)
modified = False
if event_type == "message_start":
modified = self._fix_message_start(data_json)
elif event_type == "message_delta":
modified, usage = self._fix_message_delta(data_json)
if usage:
last_usage = usage
elif event_type == "message_stop":
modified = self._fix_message_stop(
data_json, last_usage
)
if modified:
yield self._rebuild_sse(event_type, data_json)
else:
yield chunk
except Exception:
yield chunk
hook = AnthropicSchemaFixerHook()
修复后流式响应正常。这个 Hook 不能省------不修复会 fallback 到非流式模式,SageMaker 容易 60 秒超时。
效果
| 指标 | 数据 |
|---|---|
| 支线任务占比 | ~60%-65% |
| 成本降低 | ~70% |
| 性价比提升 | ~3.2 倍 |
| 开发者体验 | 无感 |
| 代码安全 | 支线不出 VPC |
踩坑清单
- 实例选型 OOM:部署前算显存,宁大勿小
- Schema 不兼容:Claude Code 更新快,Schema 修复 Hook 得跟着调
- 路由误判:单特征匹配不靠谱,至少 3 个特征才路由
- 冷启动慢:SageMaker 第一次请求会慢,配 provisioned concurrency
- 版本锁定 :LiteLLM 锁
v1.82.3-stable,别随便升
参考链接
- 代码仓库:github.com/ybalbert001...
- 部署工具:github.com/ybalbert001...
- LiteLLM:docs.litellm.ai/
- SGLang:github.com/sgl-project...
- 亚马逊云科技官博:aws.amazon.com/cn/blogs/ch...
Kimi-K2.5 和 GLM-5 处理支线完全够用,下一步把翻译总结也分流。Token 费用还有压的空间。
评论区聊聊,互相避坑 🤝