# 官方兼容层的做法(现成参考实现) 各家自己都做了"接受他家格式"的兼容层。它们踩过的坑和做出的取舍,正好是中转站的设计参考——尤其是**"忽略 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 模型名。 官方定位明确写着:**主要用于测试和能力对比,不建议作为长期生产方案**。 ### 核心行为差异 1. **`strict` 被忽略** —— 工具调用 JSON 不保证符合 schema。要严格保证得用原生 Structured Outputs。 2. **音频输入被忽略并从输入中剥离**(不报错)。 3. **Prompt caching 不支持**(原生 SDK 支持)。 4. **system/developer 消息被提升并拼接**:所有 system/developer 消息用**单个 `\n`** 连接成一条,放在对话最前面。 5. **大部分不支持的字段静默忽略,不报错。** ### 参数支持表 | 支持 | 部分支持 | 忽略 | | --- | --- | --- | | `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` 透传: ```python 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. 对本项目的设计启示 1. **"静默忽略"是行业默认做法**,但它把调试成本转嫁给用户。建议: - 默认静默忽略(保持生态兼容); - 同时通过响应 header(如 `x-gateway-dropped-params`)或可选的严格模式(`?strict=1`)暴露被丢弃的参数。 - **对会改变语义的丢弃(图片、音频、工具 strict)必须有更强的信号**,不能和 `seed` 这种无害丢弃一视同仁。 2. **模型名兜底要谨慎**。DeepSeek 的"未知名字 → flash"会掩盖拼写错误。建议白名单 + 显式别名表,未匹配则 404。 3. **错误消息不要求等价,但格式必须等价**。Anthropic 兼容层的态度是对的:格式对齐,消息内容不承诺。 4. **能力降级要分级**: - 无害(`seed`、`logit_bias`、`metadata`)→ 静默丢 - 影响质量(`temperature` clamp、`top_k` 丢弃)→ 记录日志 - 改变语义(图片被丢、`strict` 失效、`n>1` 退化)→ 报错或强提示