欢迎光临
我们一直在努力

国产大模型接入实战:基于 LiteLLM 打通通义千问、DeepSeek、MiniMax

摘要:Claude Code Haha 原版绑定 Anthropic API,对国内开发者极不友好。本文手把手教你通过 LiteLLM 代理,将通义千问、DeepSeek、MiniMax 等国产大模型接入 cc-haha,实现真正的"模型自由"。从协议转换原理到 .env 配置,从单模型到多模型热切换,全文提供可直接复制的配置模板和 Python 自动化脚本。


一、为什么国产模型接入是个难题

Claude Code 基于 Anthropic Messages API 协议通信。这套协议与 OpenAI 的 Chat Completions API 有本质区别:

  • 请求格式不同:Anthropic 使用 messages + system 分离,OpenAI 使用统一的 messages 列表
  • 流式响应不同:Anthropic 是 Server-Sent Events with event: content_block_delta,OpenAI 是 SSE with data: {…}
  • 专有参数不同:Anthropic 有 thinking、cache_control 等 OpenAI 不认识的参数

国内大模型厂商(阿里云百炼、DeepSeek、MiniMax)几乎全部采用 OpenAI 兼容接口。这意味着:不做协议转换,cc-haha 根本无法调用国产模型。

通义千问 API

LiteLLM Proxy

Anthropic API

cc-haha CLI

通义千问 API

LiteLLM Proxy

Anthropic API

cc-haha CLI

#mermaid-svg-cXZQGzg2dyQJSm1d{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cXZQGzg2dyQJSm1d .error-icon{fill:#552222;}#mermaid-svg-cXZQGzg2dyQJSm1d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cXZQGzg2dyQJSm1d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cXZQGzg2dyQJSm1d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cXZQGzg2dyQJSm1d .marker.cross{stroke:#333333;}#mermaid-svg-cXZQGzg2dyQJSm1d svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cXZQGzg2dyQJSm1d p{margin:0;}#mermaid-svg-cXZQGzg2dyQJSm1d .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cXZQGzg2dyQJSm1d text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cXZQGzg2dyQJSm1d .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-cXZQGzg2dyQJSm1d .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-cXZQGzg2dyQJSm1d #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-cXZQGzg2dyQJSm1d .sequenceNumber{fill:white;}#mermaid-svg-cXZQGzg2dyQJSm1d #sequencenumber{fill:#333;}#mermaid-svg-cXZQGzg2dyQJSm1d #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-cXZQGzg2dyQJSm1d .messageText{fill:#333;stroke:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cXZQGzg2dyQJSm1d .labelText,#mermaid-svg-cXZQGzg2dyQJSm1d .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .loopText,#mermaid-svg-cXZQGzg2dyQJSm1d .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cXZQGzg2dyQJSm1d .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-cXZQGzg2dyQJSm1d .noteText,#mermaid-svg-cXZQGzg2dyQJSm1d .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-cXZQGzg2dyQJSm1d .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cXZQGzg2dyQJSm1d .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cXZQGzg2dyQJSm1d .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cXZQGzg2dyQJSm1d .actorPopupMenu{position:absolute;}#mermaid-svg-cXZQGzg2dyQJSm1d .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-cXZQGzg2dyQJSm1d .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cXZQGzg2dyQJSm1d .actor-man circle,#mermaid-svg-cXZQGzg2dyQJSm1d line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-cXZQGzg2dyQJSm1d :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

原生支持

Anthropic 协议

直接调用

不兼容 ❌

通过 LiteLLM 代理 ✅

POST /v1/messages

Anthropic 格式 ✅

POST /v1/messages

Anthropic 格式 → 400 Error

POST /v1/messages

Anthropic 格式

协议转换

丢弃专有参数

POST /compatible-mode/v1/chat/completions

OpenAI 格式

SSE 流式响应

SSE 流式响应

Anthropic 格式


二、LiteLLM:一把钥匙开所有锁

LiteLLM 是一个开源的 LLM 代理网关,核心能力是统一接入 100+ 模型,并支持接收 Anthropic 协议请求。它的工作原理是"中间人代理":

#mermaid-svg-FjYKROiievjNhUGp{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FjYKROiievjNhUGp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FjYKROiievjNhUGp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FjYKROiievjNhUGp .error-icon{fill:#552222;}#mermaid-svg-FjYKROiievjNhUGp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FjYKROiievjNhUGp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FjYKROiievjNhUGp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FjYKROiievjNhUGp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FjYKROiievjNhUGp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FjYKROiievjNhUGp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FjYKROiievjNhUGp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FjYKROiievjNhUGp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FjYKROiievjNhUGp .marker.cross{stroke:#333333;}#mermaid-svg-FjYKROiievjNhUGp svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FjYKROiievjNhUGp p{margin:0;}#mermaid-svg-FjYKROiievjNhUGp .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-FjYKROiievjNhUGp .cluster-label text{fill:#333;}#mermaid-svg-FjYKROiievjNhUGp .cluster-label span{color:#333;}#mermaid-svg-FjYKROiievjNhUGp .cluster-label span p{background-color:transparent;}#mermaid-svg-FjYKROiievjNhUGp .label text,#mermaid-svg-FjYKROiievjNhUGp span{fill:#333;color:#333;}#mermaid-svg-FjYKROiievjNhUGp .node rect,#mermaid-svg-FjYKROiievjNhUGp .node circle,#mermaid-svg-FjYKROiievjNhUGp .node ellipse,#mermaid-svg-FjYKROiievjNhUGp .node polygon,#mermaid-svg-FjYKROiievjNhUGp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FjYKROiievjNhUGp .rough-node .label text,#mermaid-svg-FjYKROiievjNhUGp .node .label text,#mermaid-svg-FjYKROiievjNhUGp .image-shape .label,#mermaid-svg-FjYKROiievjNhUGp .icon-shape .label{text-anchor:middle;}#mermaid-svg-FjYKROiievjNhUGp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FjYKROiievjNhUGp .rough-node .label,#mermaid-svg-FjYKROiievjNhUGp .node .label,#mermaid-svg-FjYKROiievjNhUGp .image-shape .label,#mermaid-svg-FjYKROiievjNhUGp .icon-shape .label{text-align:center;}#mermaid-svg-FjYKROiievjNhUGp .node.clickable{cursor:pointer;}#mermaid-svg-FjYKROiievjNhUGp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FjYKROiievjNhUGp .arrowheadPath{fill:#333333;}#mermaid-svg-FjYKROiievjNhUGp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FjYKROiievjNhUGp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FjYKROiievjNhUGp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FjYKROiievjNhUGp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FjYKROiievjNhUGp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FjYKROiievjNhUGp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FjYKROiievjNhUGp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FjYKROiievjNhUGp .cluster text{fill:#333;}#mermaid-svg-FjYKROiievjNhUGp .cluster span{color:#333;}#mermaid-svg-FjYKROiievjNhUGp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FjYKROiievjNhUGp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FjYKROiievjNhUGp rect.text{fill:none;stroke-width:0;}#mermaid-svg-FjYKROiievjNhUGp .icon-shape,#mermaid-svg-FjYKROiievjNhUGp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FjYKROiievjNhUGp .icon-shape p,#mermaid-svg-FjYKROiievjNhUGp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FjYKROiievjNhUGp .icon-shape .label rect,#mermaid-svg-FjYKROiievjNhUGp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FjYKROiievjNhUGp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FjYKROiievjNhUGp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FjYKROiievjNhUGp :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

Anthropic 协议

OpenAI 协议

OpenAI 协议

Anthropic 协议

OpenAI 协议

Anthropic 协议

cc-haha

LiteLLM Proxy

通义千问

DeepSeek

MiniMax

Ollama 本地

OpenRouter

协议转换层

drop_params: true

格式映射

错误转换

2.1 安装 LiteLLM

# 推荐使用独立 Python 环境
python3 -m venv ~/.venvs/litellm
source ~/.venvs/litellm/bin/activate

# 安装带 proxy 功能的完整版
pip install 'litellm[proxy]'

# 验证安装
litellm –version

2.2 配置文件:litellm_config.yaml

这是整个接入流程的核心。下面提供一份生产就绪的多模型配置:

# ============================================================
# LiteLLM 配置文件:支持通义千问 + DeepSeek + MiniMax + Ollama
# ============================================================

model_list:
# —- 通义千问(阿里云百炼 / DashScope)—-
– model_name: qwen–max
litellm_params:
model: openai/qwen–max
api_key: os.environ/DASHSCOPE_API_KEY
api_base: https://dashscope.aliyuncs.com/compatible–mode/v1

– model_name: qwen–plus
litellm_params:
model: openai/qwen–plus
api_key: os.environ/DASHSCOPE_API_KEY
api_base: https://dashscope.aliyuncs.com/compatible–mode/v1

– model_name: qwen–turbo
litellm_params:
model: openai/qwen–turbo
api_key: os.environ/DASHSCOPE_API_KEY
api_base: https://dashscope.aliyuncs.com/compatible–mode/v1

# —- DeepSeek —-
– model_name: deepseek–chat
litellm_params:
model: deepseek/deepseek–chat
api_key: os.environ/DEEPSEEK_API_KEY
api_base: https://api.deepseek.com

– model_name: deepseek–coder
litellm_params:
model: deepseek/deepseek–coder
api_key: os.environ/DEEPSEEK_API_KEY
api_base: https://api.deepseek.com

# —- MiniMax(直连 Anthropic 兼容接口)—-
– model_name: minimax–m2.7
litellm_params:
model: anthropic/MiniMax–M2.7
api_key: os.environ/MINIMAX_API_KEY
api_base: https://api.minimaxi.com/anthropic

# —- 本地 Ollama(可选)—-
– model_name: llama3
litellm_params:
model: ollama/llama3
api_base: http://localhost:11434

# —- 关键全局设置 —-
litellm_settings:
# 丢弃 Anthropic 专有参数(thinking、cache_control 等)
drop_params: true

# 部分国产模型只支持 /v1/chat/completions
# 此选项强制 LiteLLM 使用该端点而非 /v1/messages
use_chat_completions_url_for_anthropic_messages: true

# 请求超时(毫秒)
request_timeout: 120

# 失败重试
num_retries: 2

关键参数说明:

  • drop_params: true:必须开启。cc-haha 会发送 thinking 等 Anthropic 专有参数,如果不丢弃,国产模型会直接报错。
  • use_chat_completions_url_for_anthropic_messages: true:强制使用 OpenAI 的 chat completions 端点,解决部分国产模型不支持 Anthropic /v1/messages 的问题。

2.3 启动代理

# 设置环境变量(从各平台控制台获取)
export DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxx
export DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx
export MINIMAX_API_KEY=xxxxxxxxxxxxxxxx

# 启动代理(默认监听 4000 端口)
litellm –config litellm_config.yaml –port 4000

# 验证代理是否正常工作
curl http://localhost:4000/v1/models


三、cc-haha 端配置:.env 文件详解

3.1 基础配置模板

# ============================================================
# cc-haha 环境变量配置
# 指向本地 LiteLLM 代理
# ============================================================

# 认证令牌(使用 LiteLLM 代理时可填任意值,除非设置了 master_key)
ANTHROPIC_AUTH_TOKEN=sk-anything

# Base URL:LiteLLM 代理地址
# ⚠️ 注意:不要带 /v1 后缀!Anthropic SDK 会自动拼接
ANTHROPIC_BASE_URL=http://localhost:4000

# 默认模型(对应 litellm_config.yaml 中的 model_name)
ANTHROPIC_MODEL=qwen-max

# 三档模型映射(cc-haha 内部使用 sonnet/haiku/opus 区分任务复杂度)
ANTHROPIC_DEFAULT_SONNET_MODEL=qwen-plus
ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen-turbo
ANTHROPIC_DEFAULT_OPUS_MODEL=qwen-max

# API 超时(毫秒)
API_TIMEOUT_MS=3000000

# 禁用遥测和非必要网络请求(建议始终开启)
DISABLE_TELEMETRY=1
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1

3.2 ⚠️ 最常见的配置错误

#mermaid-svg-dX79ke4RA1rH0PUV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dX79ke4RA1rH0PUV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dX79ke4RA1rH0PUV .error-icon{fill:#552222;}#mermaid-svg-dX79ke4RA1rH0PUV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dX79ke4RA1rH0PUV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dX79ke4RA1rH0PUV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dX79ke4RA1rH0PUV .marker.cross{stroke:#333333;}#mermaid-svg-dX79ke4RA1rH0PUV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dX79ke4RA1rH0PUV p{margin:0;}#mermaid-svg-dX79ke4RA1rH0PUV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dX79ke4RA1rH0PUV .cluster-label text{fill:#333;}#mermaid-svg-dX79ke4RA1rH0PUV .cluster-label span{color:#333;}#mermaid-svg-dX79ke4RA1rH0PUV .cluster-label span p{background-color:transparent;}#mermaid-svg-dX79ke4RA1rH0PUV .label text,#mermaid-svg-dX79ke4RA1rH0PUV span{fill:#333;color:#333;}#mermaid-svg-dX79ke4RA1rH0PUV .node rect,#mermaid-svg-dX79ke4RA1rH0PUV .node circle,#mermaid-svg-dX79ke4RA1rH0PUV .node ellipse,#mermaid-svg-dX79ke4RA1rH0PUV .node polygon,#mermaid-svg-dX79ke4RA1rH0PUV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dX79ke4RA1rH0PUV .rough-node .label text,#mermaid-svg-dX79ke4RA1rH0PUV .node .label text,#mermaid-svg-dX79ke4RA1rH0PUV .image-shape .label,#mermaid-svg-dX79ke4RA1rH0PUV .icon-shape .label{text-anchor:middle;}#mermaid-svg-dX79ke4RA1rH0PUV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dX79ke4RA1rH0PUV .rough-node .label,#mermaid-svg-dX79ke4RA1rH0PUV .node .label,#mermaid-svg-dX79ke4RA1rH0PUV .image-shape .label,#mermaid-svg-dX79ke4RA1rH0PUV .icon-shape .label{text-align:center;}#mermaid-svg-dX79ke4RA1rH0PUV .node.clickable{cursor:pointer;}#mermaid-svg-dX79ke4RA1rH0PUV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dX79ke4RA1rH0PUV .arrowheadPath{fill:#333333;}#mermaid-svg-dX79ke4RA1rH0PUV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dX79ke4RA1rH0PUV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dX79ke4RA1rH0PUV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dX79ke4RA1rH0PUV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dX79ke4RA1rH0PUV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dX79ke4RA1rH0PUV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dX79ke4RA1rH0PUV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dX79ke4RA1rH0PUV .cluster text{fill:#333;}#mermaid-svg-dX79ke4RA1rH0PUV .cluster span{color:#333;}#mermaid-svg-dX79ke4RA1rH0PUV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dX79ke4RA1rH0PUV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dX79ke4RA1rH0PUV rect.text{fill:none;stroke-width:0;}#mermaid-svg-dX79ke4RA1rH0PUV .icon-shape,#mermaid-svg-dX79ke4RA1rH0PUV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dX79ke4RA1rH0PUV .icon-shape p,#mermaid-svg-dX79ke4RA1rH0PUV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dX79ke4RA1rH0PUV .icon-shape .label rect,#mermaid-svg-dX79ke4RA1rH0PUV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dX79ke4RA1rH0PUV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dX79ke4RA1rH0PUV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dX79ke4RA1rH0PUV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

配置错误

Base URL 带 /v1 后缀

忘记 drop_params

模型名不匹配

API Key 未设置

错误: http://localhost:4000/v1

正确: http://localhost:4000

最终请求: /v1/v1/messages → 404

Anthropic 发送 thinking 参数

国产模型返回 400: unknown parameter

.env 写 qwen-max-2024

litellm 配置 qwen-max

LiteLLM 找不到模型 → 404

错误现象解决
Base URL 带 /v1 404 Not Found 去掉 /v1,只写 http://localhost:4000
未设置 drop_params 400 unknown parameter: thinking 在 litellm_config.yaml 中添加 drop_params: true
模型名不匹配 404 model not found 确保 .env 中的模型名与 litellm_config.yaml 的 model_name 完全一致
API Key 无效 401 Unauthorized 检查环境变量是否正确注入,或直接在 litellm_config.yaml 中硬编码测试

四、多模型热切换:一套配置,自由切换

在实际开发中,不同任务适合不同模型。下面提供一套Python 自动化切换工具。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
cc-haha 模型管理器
支持一键切换通义千问 / DeepSeek / MiniMax
"""

import os
import sys
import argparse
from pathlib import Path
from dataclasses import dataclass
from typing import Optional

@dataclass
class ModelProfile:
"""模型配置档案"""
name: str
display_name: str
model_id: str
sonnet: str
haiku: str
opus: str
description: str
provider: str

# 预定义模型档案库
PROFILES: dict[str, ModelProfile] = {
# 通义千问系列
"qwen-max": ModelProfile(
name="qwen-max",
display_name="通义千问-Max",
model_id="qwen-max",
sonnet="qwen-max",
haiku="qwen-turbo",
opus="qwen-max",
description="阿里云最强模型,适合复杂代码重构和架构设计",
provider="阿里云百炼"
),
"qwen-plus": ModelProfile(
name="qwen-plus",
display_name="通义千问-Plus",
model_id="qwen-plus",
sonnet="qwen-plus",
haiku="qwen-turbo",
opus="qwen-plus",
description="均衡型模型,日常编码和 Debug 首选",
provider="阿里云百炼"
),
"qwen-turbo": ModelProfile(
name="qwen-turbo",
display_name="通义千问-Turbo",
model_id="qwen-turbo",
sonnet="qwen-turbo",
haiku="qwen-turbo",
opus="qwen-turbo",
description="极速响应,适合简单问答和文档生成",
provider="阿里云百炼"
),
# DeepSeek 系列
"deepseek-chat": ModelProfile(
name="deepseek-chat",
display_name="DeepSeek-V3",
model_id="deepseek-chat",
sonnet="deepseek-chat",
haiku="deepseek-chat",
opus="deepseek-chat",
description="数学/逻辑推理强,长上下文表现出色",
provider="DeepSeek"
),
"deepseek-coder": ModelProfile(
name="deepseek-coder",
display_name="DeepSeek-Coder",
model_id="deepseek-coder",
sonnet="deepseek-coder",
haiku="deepseek-coder",
opus="deepseek-coder",
description="专为代码优化,代码补全和审查能力强",
provider="DeepSeek"
),
# MiniMax 系列
"minimax-m2.7": ModelProfile(
name="minimax-m2.7",
display_name="MiniMax-M2.7",
model_id="minimax-m2.7",
sonnet="minimax-m2.7",
haiku="MiniMax-M2.7-highspeed",
opus="minimax-m2.7",
description="国内直连 Anthropic 协议,无需 LiteLLM 转换",
provider="MiniMax"
),
}

def read_env_file(path: Path) –> list[str]:
"""读取 .env 文件为行列表"""
if not path.exists():
print(f"❌ 文件不存在: {path}")
sys.exit(1)
return path.read_text(encoding="utf-8").splitlines()

def write_env_file(path: Path, lines: list[str]) –> None:
"""写回 .env 文件"""
path.write_text("\\n".join(lines) + "\\n", encoding="utf-8")

def switch_model(env_path: Path, profile_key: str) –> None:
"""切换模型配置"""
if profile_key not in PROFILES:
print(f"❌ 未知模型: {profile_key}")
print(f"可用选项: {', '.join(PROFILES.keys())}")
sys.exit(1)

profile = PROFILES[profile_key]
lines = read_env_file(env_path)

# 需要替换的配置项
replacements = {
"ANTHROPIC_MODEL": profile.model_id,
"ANTHROPIC_DEFAULT_SONNET_MODEL": profile.sonnet,
"ANTHROPIC_DEFAULT_HAIKU_MODEL": profile.haiku,
"ANTHROPIC_DEFAULT_OPUS_MODEL": profile.opus,
}

new_lines = []
modified = set()

for line in lines:
stripped = line.strip()
# 保留注释和空行
if not stripped or stripped.startswith("#"):
new_lines.append(line)
continue

# 尝试匹配替换
for key, value in replacements.items():
if stripped.startswith(f"{key}="):
# 保留行内注释
comment = ""
if " #" in stripped:
comment = stripped[stripped.index(" #"):]
new_lines.append(f"{key}={value}{comment}")
modified.add(key)
break
else:
new_lines.append(line)

# 追加遗漏的键
for key, value in replacements.items():
if key not in modified:
new_lines.append(f"{key}={value}")

write_env_file(env_path, new_lines)

print(f"✅ 已切换至: {profile.display_name}")
print(f" 提供商: {profile.provider}")
print(f" 描述: {profile.description}")
print(f" 模型映射: Sonnet={profile.sonnet}, Haiku={profile.haiku}, Opus={profile.opus}")

def list_models() –> None:
"""列出所有可用模型"""
print("📋 可用模型列表\\n")
print(f"{'键名':<20} {'显示名':<18} {'提供商':<12} {'描述'}")
print("-" * 80)
for key, profile in PROFILES.items():
print(f"{key:<20} {profile.display_name:<18} {profile.provider:<12} {profile.description}")

def current_model(env_path: Path) –> Optional[str]:
"""读取当前配置的模型"""
lines = read_env_file(env_path)
for line in lines:
if line.strip().startswith("ANTHROPIC_MODEL=") and not line.strip().startswith("#"):
return line.strip().split("=", 1)[1]
return None

def main() –> None:
parser = argparse.ArgumentParser(
description="cc-haha 模型切换工具",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
# 列出所有模型
python model_manager.py –list

# 切换到通义千问 Max
python model_manager.py –model qwen-max

# 切换到 DeepSeek
python model_manager.py –model deepseek-chat –env ~/cc-haha/.env

# 查看当前模型
python model_manager.py –current –env ~/cc-haha/.env
"""
)
parser.add_argument("–model", "-m", choices=list(PROFILES.keys()), help="目标模型")
parser.add_argument("–env", "-e", type=Path, default=Path(".env"), help=".env 文件路径")
parser.add_argument("–list", "-l", action="store_true", help="列出所有模型")
parser.add_argument("–current", "-c", action="store_true", help="查看当前模型")

args = parser.parse_args()

if args.list:
list_models()
elif args.current:
model = current_model(args.env)
print(f"当前模型: {model or '未配置'}")
elif args.model:
switch_model(args.env, args.model)
else:
parser.print_help()

if __name__ == "__main__":
main()

4.1 使用示例

# 查看所有可用模型
python model_manager.py –list

# 日常开发用 qwen-plus(均衡)
python model_manager.py –model qwen-plus

# 复杂任务用 qwen-max(最强)
python model_manager.py –model qwen-max

# 快速问答用 qwen-turbo(最快)
python model_manager.py –model qwen-turbo

# 逻辑推理任务用 DeepSeek
python model_manager.py –model deepseek-chat


五、模型选择决策树

#mermaid-svg-peqbFABSMHAsl57H{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-peqbFABSMHAsl57H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-peqbFABSMHAsl57H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-peqbFABSMHAsl57H .error-icon{fill:#552222;}#mermaid-svg-peqbFABSMHAsl57H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-peqbFABSMHAsl57H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-peqbFABSMHAsl57H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-peqbFABSMHAsl57H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-peqbFABSMHAsl57H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-peqbFABSMHAsl57H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-peqbFABSMHAsl57H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-peqbFABSMHAsl57H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-peqbFABSMHAsl57H .marker.cross{stroke:#333333;}#mermaid-svg-peqbFABSMHAsl57H svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-peqbFABSMHAsl57H p{margin:0;}#mermaid-svg-peqbFABSMHAsl57H .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-peqbFABSMHAsl57H .cluster-label text{fill:#333;}#mermaid-svg-peqbFABSMHAsl57H .cluster-label span{color:#333;}#mermaid-svg-peqbFABSMHAsl57H .cluster-label span p{background-color:transparent;}#mermaid-svg-peqbFABSMHAsl57H .label text,#mermaid-svg-peqbFABSMHAsl57H span{fill:#333;color:#333;}#mermaid-svg-peqbFABSMHAsl57H .node rect,#mermaid-svg-peqbFABSMHAsl57H .node circle,#mermaid-svg-peqbFABSMHAsl57H .node ellipse,#mermaid-svg-peqbFABSMHAsl57H .node polygon,#mermaid-svg-peqbFABSMHAsl57H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-peqbFABSMHAsl57H .rough-node .label text,#mermaid-svg-peqbFABSMHAsl57H .node .label text,#mermaid-svg-peqbFABSMHAsl57H .image-shape .label,#mermaid-svg-peqbFABSMHAsl57H .icon-shape .label{text-anchor:middle;}#mermaid-svg-peqbFABSMHAsl57H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-peqbFABSMHAsl57H .rough-node .label,#mermaid-svg-peqbFABSMHAsl57H .node .label,#mermaid-svg-peqbFABSMHAsl57H .image-shape .label,#mermaid-svg-peqbFABSMHAsl57H .icon-shape .label{text-align:center;}#mermaid-svg-peqbFABSMHAsl57H .node.clickable{cursor:pointer;}#mermaid-svg-peqbFABSMHAsl57H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-peqbFABSMHAsl57H .arrowheadPath{fill:#333333;}#mermaid-svg-peqbFABSMHAsl57H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-peqbFABSMHAsl57H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-peqbFABSMHAsl57H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-peqbFABSMHAsl57H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-peqbFABSMHAsl57H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-peqbFABSMHAsl57H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-peqbFABSMHAsl57H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-peqbFABSMHAsl57H .cluster text{fill:#333;}#mermaid-svg-peqbFABSMHAsl57H .cluster span{color:#333;}#mermaid-svg-peqbFABSMHAsl57H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-peqbFABSMHAsl57H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-peqbFABSMHAsl57H rect.text{fill:none;stroke-width:0;}#mermaid-svg-peqbFABSMHAsl57H .icon-shape,#mermaid-svg-peqbFABSMHAsl57H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-peqbFABSMHAsl57H .icon-shape p,#mermaid-svg-peqbFABSMHAsl57H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-peqbFABSMHAsl57H .icon-shape .label rect,#mermaid-svg-peqbFABSMHAsl57H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-peqbFABSMHAsl57H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-peqbFABSMHAsl57H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-peqbFABSMHAsl57H :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

高架构设计/大规模重构

中日常编码/Debug

低快速问答/文档

是

是

否

任务类型

复杂度?

qwen-max / deepseek-chat

qwen-plus / deepseek-coder

qwen-turbo

是否需要 Anthropic 协议?

MiniMax-M2.7直连免转换

预算敏感?

qwen-turbo cheapest

qwen-max best quality

场景推荐模型理由
大型项目重构 qwen-max 上下文理解强,能协调多文件修改
日常 Bug 修复 qwen-plus 性价比最优,响应速度适中
算法/数学题 deepseek-chat 逻辑推理和数学能力突出
代码审查 deepseek-coder 专为代码优化训练
快速问答 qwen-turbo 延迟最低,成本低
国内直连免代理 MiniMax-M2.7 原生 Anthropic 兼容接口

六、生产环境进阶配置

6.1 多 LiteLLM 实例负载均衡

对于团队使用场景,可以部署多个 LiteLLM 实例,通过 Nginx 做负载均衡:

upstream litellm {
server 127.0.0.1:4000;
server 127.0.0.1:4001;
server 127.0.0.1:4002;
}

server {
listen 8080;
location / {
proxy_pass http://litellm;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

6.2 请求日志与审计

LiteLLM 支持详细的请求日志,便于排查问题和审计:

litellm_settings:
success_callback: ["langfuse"]
failure_callback: ["langfuse"]

# 或自定义 webhook
success_callback: ["custom_handler"]

6.3 速率限制与配额管理

model_list:
– model_name: qwen–max
litellm_params:
model: openai/qwen–max
api_key: os.environ/DASHSCOPE_API_KEY
api_base: https://dashscope.aliyuncs.com/compatible–mode/v1
# 每分钟最多 10 次请求
rpm: 10
# 每分钟最多 10000 tokens
tpm: 10000


七、常见问题深度解答

Q1: LiteLLM 代理报错 /v1/responses 找不到?

原因:部分国产模型只支持 /v1/chat/completions,不支持 Anthropic 的 /v1/messages。

解决:在 litellm_config.yaml 中设置:

litellm_settings:
use_chat_completions_url_for_anthropic_messages: true

Q2: 模型输出乱码或截断?

原因:编码问题或 max_tokens 设置过小。

解决:检查 .env 中的 API_TIMEOUT_MS 是否足够大(建议 3000000),并在 LiteLLM 中设置合理的 max_tokens。

Q3: 如何同时配置多个模型并动态切换?

解决:在 litellm_config.yaml 中配置多个 model_name,然后通过修改 .env 中的 ANTHROPIC_MODEL 切换。不需要重启 LiteLLM,只需要重启 cc-haha。

Q4: 本地 Ollama 模型效果不好?

原因:cc-haha 大量使用工具调用(tool_use),对小模型要求很高。

建议:使用 70B 以上的模型(如 Llama 3 70B、Qwen 72B),小模型(7B/13B)几乎无法正确处理工具调用。


总结

通过 LiteLLM 代理,cc-haha 彻底打破了"只能用 Claude"的枷锁。本文提供了:

  • 完整的 litellm_config.yaml:支持通义千问、DeepSeek、MiniMax、Ollama 五类模型
  • 生产级 .env 配置模板:包含所有关键参数和常见错误提醒
  • Python 自动化切换工具:一键在不同模型间切换
  • 模型选择决策树:根据任务类型快速选型
  • 最佳实践:建议每个开发者维护一份自己的 litellm_config.yaml,按使用频率排列模型顺序。日常开发用 qwen-plus 或 deepseek-chat,复杂任务切 qwen-max,简单问答用 qwen-turbo。


    参考资料

  • LiteLLM 官方文档
  • 阿里云百炼控制台
  • DeepSeek API 文档
  • MiniMax 开放平台
  • cc-haha 第三方模型指南
  • Anthropic Messages API
  • OpenAI Chat Completions API

  • 本文配置经过实际验证,可直接复制使用。如遇问题,建议先检查 ANTHROPIC_BASE_URL 是否带 /v1 后缀——这是 90% 配置问题的根源。

    赞(0)
    未经允许不得转载:171主机测评 » 国产大模型接入实战:基于 LiteLLM 打通通义千问、DeepSeek、MiniMax
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址