5.7 KiB
官方兼容层的做法(现成参考实现)
各家自己都做了"接受他家格式"的兼容层。它们踩过的坑和做出的取舍,正好是中转站的设计参考——尤其是**"忽略 vs 报错"的边界划在哪里**。
来源:
- https://platform.claude.com/docs/en/api/openai-sdk
- https://api-docs.deepseek.com/guides/anthropic_api
- https://api-docs.deepseek.com/guides/responses_api
采集于 2026-08-12。
1. Anthropic 的 OpenAI SDK 兼容层
Base URL:https://api.anthropic.com/v1/,用 Anthropic API key,模型名填 Claude 模型名。
官方定位明确写着:主要用于测试和能力对比,不建议作为长期生产方案。
核心行为差异
strict被忽略 —— 工具调用 JSON 不保证符合 schema。要严格保证得用原生 Structured Outputs。- 音频输入被忽略并从输入中剥离(不报错)。
- Prompt caching 不支持(原生 SDK 支持)。
- system/developer 消息被提升并拼接:所有 system/developer 消息用单个
\n连接成一条,放在对话最前面。 - 大部分不支持的字段静默忽略,不报错。
参数支持表
| 支持 | 部分支持 | 忽略 |
|---|---|---|
model、max_tokens、max_completion_tokens、stream、stream_options、top_p、parallel_tool_calls |
stop(仅非空白停止序列)temperature(0~1,>1 截断为 1)n(必须恰为 1) |
logprobs、top_logprobs、metadata、response_format、prediction、presence_penalty、frequency_penalty、seed、service_tier、audio、logit_bias、store、user、modalities、reasoning_effort |
消息字段层面:
| 位置 | 忽略的字段 |
|---|---|
| 所有 role | name |
user + image_url |
detail |
| user | input_audio、file 类型 content |
| assistant | refusal content、audio、refusal |
| tools | function.strict |
响应字段
| 恒定行为 | 字段 |
|---|---|
| 长度恒为 1 | choices[] |
| 恒为空 | usage.completion_tokens_details、usage.prompt_tokens_details、choices[].message.refusal、choices[].message.audio、logprobs、service_tier、system_fingerprint |
Header
支持 x-ratelimit-* 全套、retry-after、request-id、authorization。
openai-version 恒为 2020-10-01,openai-processing-ms 恒为空。
错误
错误格式与 OpenAI 一致,但错误消息内容不等价。官方明确说明:只用于日志和调试,不要基于错误消息文本做逻辑判断。
thinking 的传法
通过 extra_body 透传:
response = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": "Who are you?"}],
extra_body={"thinking": {"type": "enabled", "budget_tokens": 2000}},
)
但 OpenAI SDK 不会返回 Claude 的详细思考过程——要拿到思考内容必须用原生 API。
2. DeepSeek 的 Anthropic 兼容层
Base URL:https://api.deepseek.com/anthropic(配置 ANTHROPIC_BASE_URL)。
模型名映射(静默兜底)
| 传入 | 实际使用 |
|---|---|
claude-opus* |
deepseek-v4-pro |
claude-haiku* / claude-sonnet* |
deepseek-v4-flash |
| 其他任意值 | deepseek-v4-flash |
未知模型名不报错。这是个值得商榷的设计——用户拼错模型名会得到一个成功但非预期的响应。
支持 / 忽略
| 支持 | 忽略或不支持 |
|---|---|
model、max_tokens、system、stream、stop_sequences、tools |
anthropic-beta / anthropic-version header |
temperature(0.0~2.0,比官方 Anthropic 的 0~1 宽) |
image / document content 类型 |
thinking(但 budget_tokens 被忽略) |
top_k |
metadata.user_id(用于限流隔离) |
其他 metadata 字段 |
思考参数命名不一致
DeepSeek 的 Anthropic 入口用 reasoning.effort,而官方 Anthropic API 用 thinking + output_config.effort。
换句话说:同一段客户端代码不能同时对接官方 Anthropic 和 DeepSeek 的 Anthropic 入口。
3. DeepSeek 的 Responses API 兼容层
Base URL:https://api.deepseek.com,目前只支持 deepseek-v4-flash。
- "未支持的参数一律静默忽略,不报错" —— 官方明文的设计原则,理由是不破坏既有实现。
store恒返回false。previous_response_id、conversation不支持(无状态架构)。- 上下文缓存自动进行,无手动参数。
- image / file 输入被替换成占位文本。这是"静默忽略"里最危险的一种:请求成功、响应看起来正常,但模型根本没看到图片。
4. 对本项目的设计启示
- "静默忽略"是行业默认做法,但它把调试成本转嫁给用户。建议:
- 默认静默忽略(保持生态兼容);
- 同时通过响应 header(如
x-gateway-dropped-params)或可选的严格模式(?strict=1)暴露被丢弃的参数。 - 对会改变语义的丢弃(图片、音频、工具 strict)必须有更强的信号,不能和
seed这种无害丢弃一视同仁。
- 模型名兜底要谨慎。DeepSeek 的"未知名字 → flash"会掩盖拼写错误。建议白名单 + 显式别名表,未匹配则 404。
- 错误消息不要求等价,但格式必须等价。Anthropic 兼容层的态度是对的:格式对齐,消息内容不承诺。
- 能力降级要分级:
- 无害(
seed、logit_bias、metadata)→ 静默丢 - 影响质量(
temperatureclamp、top_k丢弃)→ 记录日志 - 改变语义(图片被丢、
strict失效、n>1退化)→ 报错或强提示
- 无害(