03 多协议支持:一个模型同时讲 OpenAI、Responses 和 Anthropic 三种"方言"

《DeepSeek-V4-Flash 本地部署与公网服务化》系列 · 第 ③ 篇 / 共 5 篇
① 硬件选型与 llama.cpp 部署② API 鉴权与腾讯云公网桥接③ 多协议支持:Anthropic 与 Responses API(本篇)④ 稳定性与性能调优实录⑤ 客户端接入:pi 与各类 SDK

llama-server 原生只说 OpenAI Chat Completions。本篇用 LiteLLM 加一层协议翻译,让同一个模型同时支持 Anthropic Messages(Claude Code 等)和 OpenAI Responses(Codex CLI 等)。

1. 架构与落点选择

OpenAI 客户端   → /v1/*                → 直连 llama-server:8081(无损)
Responses 客户端 → /v1/responses        → LiteLLM:8090 → llama-server:8081
Anthropic 客户端 → /anthropic/v1/*      → LiteLLM:8090 → llama-server:8081

shim 放在模型机(local-server,503GB 内存)而不是跳板机——跳板机只有 945MB 内存,LiteLLM 依赖树(fastapi/uvicorn/openai/pydantic/tiktoken…)跑起来就要几百 MB。为此把 02 篇的隧道扩成双端口(8081 模型 + 8090 shim),跳板机侧 permitlisten 和 iptables 同步加 8090。

2. 安装(含两个坑)

模型机没有 python3-venv 且不想动 sudo,用 --without-pip + get-pip 引导:

python3 -m venv --without-pip ~/deepseek-v4-flash/shim-venv
curl -sSL https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py
~/deepseek-v4-flash/shim-venv/bin/python /tmp/get-pip.py -i https://pypi.tuna.tsinghua.edu.cn/simple
~/deepseek-v4-flash/shim-venv/bin/pip install -i https://pypi.tuna.tsinghua.edu.cn/simple \
  "litellm[proxy]" "fastapi==0.115.12" "sse-starlette==2.2.1"

坑 1:litellm 1.96.2 与最新 fastapi(0.141.x)不兼容——litellm/proxy/management_endpoints/.../common.py 引用了 fastapi 0.12x 移除的内部函数 get_flat_dependant,启动即 ImportError。锁 fastapi==0.115.12 解决。

坑 2:锁了旧 fastapi 后 starlette 被拉到 0.46,而 sse-starlette 3.4.8 要求 starlette≥0.49——SSE 流式会埋雷。再锁 sse-starlette==2.2.1 对齐。

3. LiteLLM 配置

~/deepseek-v4-flash/litellm_config.yaml

model_list:
  - model_name: deepseek-v4-flash          # 主名
    litellm_params:
      model: openai/deepseek-v4-flash      # openai/ 前缀 = OpenAI 兼容端点
      api_base: http://127.0.0.1:8081/v1
      api_key: os.environ/DS_API_KEY       # 从环境变量读, 不写死
  - model_name: claude-sonnet-4-5          # 别名: Claude 系客户端不改模型名也能用
    litellm_params:
      model: openai/deepseek-v4-flash
      api_base: http://127.0.0.1:8081/v1
      api_key: os.environ/DS_API_KEY
  # claude-opus-4-5 / claude-haiku-4-5 同理...

general_settings:
  master_key: os.environ/DS_API_KEY        # 与 llama-server 同一把 key

litellm_settings:
  drop_params: true                        # 丢弃后端不认识的参数, 而不是报错

启动(tmux 会话 ds-shim):

cd ~/deepseek-v4-flash
DS_API_KEY=$(cat .api-key) ./shim-venv/bin/litellm \
  --config litellm_config.yaml --host 127.0.0.1 --port 8090

鉴权复用同一把 API key,Authorization: Bearer 和 Anthropic 风格的 x-api-key 都接受。

4. nginx 路由细节

两个新 location(80/443 两个 server block 都加):

# Anthropic: 剥前缀 /anthropic/v1/messages -> shim /v1/messages
location ^~ /anthropic/ {
    include /etc/nginx/snippets/ds-anthropic-proxy.conf;   # proxy_pass http://127.0.0.1:8090/;
}

# Responses: 比 ^~ /v1/ 前缀更长所以优先, 路径原样透传
location ^~ /v1/responses {
    include /etc/nginx/snippets/ds-responses-proxy.conf;   # proxy_pass http://127.0.0.1:8090;
}

两个技巧:/anthropic/ 用带尾斜杠的 proxy_pass http://127.0.0.1:8090/ 做前缀剥离;/v1/responses无 URIproxy_pass http://127.0.0.1:8090 保持原路径。nginx 前缀匹配取最长者,所以 /v1/responses 会精确切到 shim,其余 /v1/* 仍直连 llama-server。

5. 三种协议保真度实测

同一把 key、同一个模型,三条路径全部验证通过(非流式 + SSE 流式 + 无 key 拒绝):

能力 Chat Completions(直连) Responses(shim) Anthropic(shim)
基础对话
流式 ✅ SSE response.createdreasoning_text.delta→… 事件完整 message_startcontent_block_deltamessage_stop 完整
工具调用 ✅(tool_use 块 + stop_reason: tool_use,实测让模型"查北京天气"返回标准 tool_use)
思考内容 reasoning_content 原样 ✅ 映射为 reasoning output item ⚠️ 丢弃(不显示,但仍消耗 max_tokens)
无 key 401 500(litellm 癖性,同样拒绝) 500

Anthropic 路由的注意事项:思考被吞意味着 max_tokens 别给太小(<64 时可能整段输出都是隐藏思考,content 为空数组);客户端给 1024+ 就正常。

6. 客户端用法

Claude Code(Anthropic 协议):

ANTHROPIC_BASE_URL=https://api.example.com/anthropic \
ANTHROPIC_AUTH_TOKEN=<API_KEY> \
ANTHROPIC_MODEL=deepseek-v4-flash \
claude

Codex CLI(Responses 协议):

OPENAI_BASE_URL=https://api.example.com/v1 \
OPENAI_API_KEY=<API_KEY> \
codex -m deepseek-v4-flash

原生 Anthropic SDK

import anthropic
client = anthropic.Anthropic(base_url="https://api.example.com/anthropic", api_key="<API_KEY>")
client.messages.create(model="deepseek-v4-flash", max_tokens=1024,
                       messages=[{"role": "user", "content": "hi"}])

建议:支持多种协议的客户端(如 pi)优先走原生 Chat Completions——少一层翻译,reasoning_content 无损。Anthropic/Responses 入口是给"只认那一种协议"的客户端准备的。


上一篇02 API 鉴权与公网桥接 · 下一篇04 稳定性与性能调优实录

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐