OpenAI与Anthropic API兼容实践:一套代码接入两大LLM平台

OpenAI与Anthropic API兼容实践:一套代码接入两大LLM平台 1. 这篇行业报告真正值得关注的地方是什么AI 行业看似热闹但真正能赚到钱的公司远没有想象中多。不管是被 ChatGPT 带火的大模型热潮还是各类 AI 编程助手、AI Agent 项目的爆发资金最终都流向了同一个地方模型层。关于“70% of AI revenue comes from OpenAI and Anthropic”这个表述传递的是一个更冷静的信息AI 行业的大部分收入集中在基础设施层的头部玩家手中而不是散布在几千家做应用的创业公司里。对开发者而言这不是一个可以忽略的宏观数据它直接影响着你今天应该学什么、用什么公司的基础设施以及你未来的应用要建立在谁的平台之上。这篇文章不是要帮大家复述一份行业报告而是要解决三个具体问题为什么 AI 行业的钱会高度集中在 OpenAI 和 Anthropic 这两家公司作为普通开发者面对这种集中格局技术选型时应该怎么思考抛开宏观叙事真正落到代码层面我们如何接入、验证、对比和兼容这两家主流模型服务第三个问题最容易被行业分析类文章忽略。很多人讲完了趋势、技术路线、商业前景最后却没有给出一个能直接运行的 API 调用示例。本文会把重点放在“技术人在这个格局下应该怎么动手”上。2. AI 收入高度集中背后的技术结构2.1 为什么是模型层吃掉了大部分利润从软件开发者的视角来看AI 行业大致可以分为三层基础设施层、模型层、应用层。基础设施层提供算力和硬件优化比如 GPU 集群、芯片设计和集群调度。模型层负责训练和提供大模型 API这是 OpenAI 和 Anthropic 所在的位置。应用层则是在这些模型之上做具体业务比如客服机器人、代码生成插件、企业知识库问答、AI 写作工具等。过去十年很多软件行业的利润被应用层拿走因为基础设施已经标准化应用可以自由选择底层架构。但在大模型时代情况变了。大模型训练和推理的成本极高而且模型的智能水平、稳定性、安全性、上下文长度、指令遵循能力等核心指标直接决定了上层应用的体验上限。当开发者使用 OpenAI 的 GPT 系列或 Anthropic 的 Claude 系列时实际上是在租用别人的智能能力。这种能力迁移的成本非常高用户不会因为你把 API 调用封装得好看就忽略模型本身的质量差距。换句话说真正创造“智能”的环节拿走了大部分利润而应用层更多是在做“智能的包装和分发”。2.2 两家公司靠什么守住收入高地OpenAI 的代表性产品是 ChatGPT 和 GPT 系列模型在通用对话、代码生成、复杂推理、插件生态方面的认知度极高。Anthropic 的代表性产品是 Claude 系列在长上下文理解、安全对齐、复杂文档分析、企业级合规方面有明显的定位差异。从技术上看这两个平台有几个共同特征解释了它们为什么能锁住收入首先是 API 稳定性。企业接入模型 API 后最怕的是服务频繁不可用。两家公司都在持续优化推理基础设施逐步提升并发能力和服务可靠性。虽然仍会出现区域性故障但相比中小模型厂商整体的可用性表现更好。其次是模型迭代速度。GPT 系列和 Claude 系列都在以季度甚至更快的节奏迭代每次新版本都会在数学推理、代码能力、指令遵循、多模态理解等维度上有显著提升。应用开发者不需要更换供应商就能持续获得模型能力升级。第三是工具调用和 Agent 能力的完善程度。今天的大模型应用已经很少是简单的“提问-回答”模式大量真实业务需要模型自主决定调用哪些工具、如何解析返回结果、如何处理多轮上下文。OpenAI 和 Anthropic 在 Function Calling函数调用、Tool Use工具使用、结构化输出方面提供了相对成熟的支持这就让开发者产生了很强的技术惯性。从收入结构看模型 API 收入和订阅收入是两个主要来源。API 按 Token 计费订阅收入来自 C 端用户和企业版。这种收入结构有一个特点客户一旦在某个平台上完成了数据清洗、指令调优、工具函数的代码编写、评测流程的搭建切换成本就会变高。这不仅是产品好用不好用的问题更是工程资产转移成本的问题。2.3 对开发者的直接含义70% 集中在两家公司的数据对开发者意味着两件事。第一学习这两个平台的 API 设计和调用方式是在为未来的 AI 应用开发打基础。无论你是在做 AI Agent、AI 编程助手还是企业内部知识库大概率都会以这两个平台之一作为主力模型服务。第二不要完全押注单一平台。客观地讲OpenAI 和 Anthropic 都在快速发展但没有任何一个云服务或 API 提供商能保证永远不出故障、永远不调整价格策略、永远满足你的全部需求。更稳妥的做法是在代码层面做一层统一抽象让应用可以灵活切换底层模型。这一点会在后续章节的示例中详细演示。3. OpenAI 与 Anthropic 的技术差异与 API 兼容性问题3.1 两者最核心的差异不在对话效果而在工程能力侧重点很多开发者对 OpenAI 和 Anthropic 的认知停留在“GPT 更通用Claude 更安全”的层面。这个说法有一定道理但在实际工程里双方的差异要具体得多。OpenAI 的 API 生态更早成形第三方 SDK、框架和集成工具的数量非常多。无论是直接调用 Chat Completions 接口还是配合各类 Agent 框架做工具调用示例代码和社区资料都更丰富。如果团队里都是新手选择 OpenAI 生态的学习成本通常更低。Anthropic 在长文本处理和企业级安全场景上做了大量针对性设计。Claude 系列模型在超长文档理解、多轮复杂指令、拒绝有害请求等场景下的表现一直比较突出。如果你的业务场景涉及大量合同审查、论文分析、审计报告总结对上下文窗口和输出可控性的要求会更高Anthropic 的模型就更值得优先评估。从模型架构上说GPT 系列和 Claude 系列都在做大规模自回归语言模型但在训练策略、对齐方式、上下文处理和工具调用接口上存在差异。对于普通开发者最直接的感受不是底层的参数规模而是请求格式、响应字段、Token 计费方式、模型名称和错误码的不同。3.2 “Anthropic OpenAI API Compatible”是什么意思“Anthropic OpenAI API Compatible”是一种很常见的说法它的含义是某些第三方平台或代理服务允许你用 OpenAI SDK 的写法去调用 Anthropic 的模型或者反过来用 Anthropic 的格式去访问 OpenAI。但这不代表两家的官方接口完全一致而是指中间层帮你做了协议转换。实际开发中最常见的情况是你的代码中原本写的是openai.chat.completions.create(...)要切换成 Claude 时需要改为anthropic.beta.messages.create(...)。两个平台的请求体字段不同。OpenAI 使用messages、model、max_tokens、temperature等字段Anthropic 在 Messages API 中也使用messages和model但需要额外提供max_tokens参数系统提示词放在system字段中而不是放在消息列表里。两者的流式响应格式不同。OpenAI 的流式返回使用data:换行分隔的 SSE 格式Anthropic 则会在流式响应中区分message_start、content_block_delta等事件类型。因此虽然可以通过兼容层做到“一套代码接两家”但在真实项目中我们还是建议先理解两者的原生差异再决定要不要引入兼容方案。下面用一张表格说明普通开发者最关心的基本差异对比项OpenAIAnthropic官方 SDKopenai-python / openai-javaanthropic-sdk-python / anthropic-java核心接口Chat Completions APIMessages API系统提示词messages 列表中的 system role独立的 system 字段必填参数model、messagesmodel、messages、max_tokens工具调用function_call / toolstool_use / tool_result流式格式SSE data 字段SSE 事件流需解析事件类型模型示例以现有公开型号为例GPT-4o、GPT-4 Turbo、o1 系列Claude 3.5 Sonnet、Claude 3 Opus长上下文能力较强的上下文窗口支持同样支持超长上下文且在文档分析场景有大量案例注意上表里的模型名称和参数以官方文档为准具体型号会随时间更新。写代码时不建议硬编码模型名称最好放到配置文件中。3.3 两者协议不兼容时项目应该怎么设计两个平台协议不兼容本身不是坏事。模型厂商通过差异化 API 设计可以更灵活地调整产品能力。但对开发者来说这就意味着一个现实问题如果你的应用要同时支持 OpenAI 和 Anthropic就需要在业务代码中抽象出模型网关层而不是在业务逻辑里到处直接调用具体厂商的 SDK。在实际项目中更推荐的方式是业务层不依赖具体模型的类型。网关层根据配置动态决定请求发送到 OpenAI 还是 Anthropic。上层拿到统一的响应对象比如modelAnswer、tokenUsage、finishReason。这样的架构改造在项目初期可能显得多此一举但当模型价格变动、新模型发布、某个平台出现故障时价值就会非常明显。下一章节我们会用代码演示两种接入方式以及如何写一个最小可用的统一网关。4. 环境准备与前置条件动手之前需要先确认本机环境。本文示例基于 Python 3.10 及以上版本不依赖特定操作系统。你需要准备以下内容Python 3.10并已安装pip。一个 OpenAI 平台的 API Key。一个 Anthropic 平台的 API Key。网络能够正常访问两个 API 服务。4.1 创建 Python 虚拟环境建议在所有项目中使用虚拟环境避免依赖污染。python3 -m venv venv source venv/bin/activateWindows 系统下激活命令为venv\Scripts\activate4.2 安装依赖本文需要安装两个官方 SDKpip install openai anthropic python-dotenvopenai是 OpenAI 官方 SDK。anthropic是 Anthropic 官方 SDK。python-dotenv用来从.env文件中读取 API Key避免把密钥写进代码。版本说明本文不锁定具体 SDK 版本建议安装最新稳定版。两个 SDK 的接口在不同版本之间可能会有细微调整如果你运行示例时报错“AttributeError”或“TypeError”优先检查 SDK 版本。4.3 配置环境变量在项目根目录下创建.env文件OPENAI_API_KEYsk-your-openai-key ANTHROPIC_API_KEYsk-ant-your-anthropic-key这里有一个容易被忽略的安全问题。.env文件千万不要提交到 Git 仓库。如果你还没有创建.gitignore请立即创建并加入.env.env venv/ __pycache__/API Key 属于敏感凭证。在团队协作或生产环境中更建议使用专用的密钥管理服务而不是直接写在环境变量文件里。关于这一点后面的最佳实践章节会展开说明。5. 完整示例一套代码接入 OpenAI 和 Anthropic5.1 最小示例直接调用 OpenAI先写一个最简单的对话调用确认环境配置没有问题。文件路径examples/openai_demo.pyimport os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) def chat_with_openai(user_message: str) - str: response client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是一个简洁的技术助手。}, {role: user, content: user_message}, ], temperature0.3, ) return response.choices[0].message.content if __name__ __main__: result chat_with_openai(请用一句话介绍什么是大语言模型) print(result)运行方式python examples/openai_demo.py如果能够正常输出一句关于大语言模型的解释说明你的 OpenAI API Key 和网络环境配置成功。注意点gpt-4o-mini是一个比较经济的模型型号适合跑通流程。不同账号可用的模型列表可能不同如果报错Model not found需要登录平台后台确认你的账号可以访问哪些模型。temperature0.3用来控制输出随机性数值越小输出越稳定。实际项目中不要直接把 API Key 写在代码里。5.2 最小示例直接调用 AnthropicAnthropic 的 Messages API 调用方式与 OpenAI 类似但字段有差异。文件路径examples/anthropic_demo.pyimport os from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() client Anthropic(api_keyos.getenv(ANTHROPIC_API_KEY)) def chat_with_anthropic(user_message: str) - str: message client.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens1024, system你是一个简洁的技术助手。, messages[ {role: user, content: user_message}, ], ) return message.content[0].text if __name__ __main__: result chat_with_anthropic(请用一句话介绍什么是大语言模型) print(result)运行方式python examples/anthropic_demo.py与 OpenAI 示例的差异点必须提供max_tokens参数。Anthropic 的 API 不会使用默认最大 Token 数不传会直接报错。system是独立参数不在messages列表中。返回的content是一个列表需要取content[0].text。Claude 返回内容可以包含文本块、工具调用块等多种类型写代码时建议做类型判断而不是直接取下标。5.3 统一网关层用一套业务代码切换模型前面两个示例演示了原生调用方式但如果业务代码里满是这种直接调用后期维护就会很痛苦。我们在实际项目中更推荐的做法是定义自己的模型网关接口。这个网关不需要做成复杂的微服务。很多时候一个简单的 Python 类就够了。文件路径examples/llm_gateway.pyimport os from typing import Literal from anthropic import Anthropic from dotenv import load_dotenv from openai import OpenAI load_dotenv() BackendType Literal[openai, anthropic] class LLMGateway: 统一的 LLM 网关根据 backend 配置转发到不同厂商。 def __init__(self, backend: BackendType): self.backend backend if backend openai: self.openai_client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) self.anthropic_client None elif backend anthropic: self.anthropic_client Anthropic(api_keyos.getenv(ANTHROPIC_API_KEY)) self.openai_client None else: raise ValueError(fUnsupported backend: {backend}) self._model_map { openai: gpt-4o-mini, anthropic: claude-3-5-sonnet-20241022, } def chat(self, system_prompt: str, user_message: str) - str: if self.backend openai: return self._chat_openai(system_prompt, user_message) elif self.backend anthropic: return self._chat_anthropic(system_prompt, user_message) return def _chat_openai(self, system_prompt: str, user_message: str) - str: response self.openai_client.chat.completions.create( modelself._model_map[openai], messages[ {role: system, content: system_prompt}, {role: user, content: user_message}, ], ) return response.choices[0].message.content def _chat_anthropic(self, system_prompt: str, user_message: str) - str: message self.anthropic_client.messages.create( modelself._model_map[anthropic], max_tokens1024, systemsystem_prompt, messages[{role: user, content: user_message}], ) return message.content[0].text if __name__ __main__: for backend in [openai, anthropic]: gateway LLMGateway(backendbackend) # type: ignore[arg-type] answer gateway.chat( system_prompt你是一个简洁的技术助手。, user_message请用一句话介绍什么是大语言模型, ) print(f[{backend}] {answer})运行方式python examples/llm_gateway.py这样一个简单的网关类虽然只封装了最基本的对话能力但已经在业务逻辑和模型厂商之间建立了一层隔离。业务代码只需要关注system_prompt和user_message不需要关心背后调的是哪家模型。5.4 配一个简单的模型路由按任务类型走不同厂商在更复杂一点的场景中你可能希望做模型路由。比如 “摘要类任务走 Anthropic因为长文本处理更稳代码生成类任务走 OpenAI因为生态更成熟”。文件路径examples/model_router.pyimport os from anthropic import Anthropic from dotenv import load_dotenv from openai import OpenAI load_dotenv() openai_client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) anthropic_client Anthropic(api_keyos.getenv(ANTHROPIC_API_KEY)) def summarize_with_claude(document: str) - str: message anthropic_client.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens512, system你是一个文档摘要专家请提炼核心信息。, messages[{role: user, content: document[:12000]}], ) return message.content[0].text def generate_code_with_gpt(task_description: str) - str: response openai_client.chat.completions.create( modelgpt-4o-mini, messages[ {role: system, content: 你是一个资深 Python 工程师请只输出代码。}, {role: user, content: task_description}, ], ) return response.choices[0].message.content if __name__ __main__: # 示例长文档摘要走 Claude summary summarize_with_claude(这是一段测试文档。该文档包含销售数据、客户反馈和产品缺陷三部分内容。……) print(摘要结果, summary) # 示例代码生成走 GPT code generate_code_with_gpt(请写一个 Python 函数使用 requests 库抓取网页标题。) print(生成代码, code)这种路由策略的优点在于你可以根据不同模型在不同任务上的表现、价格、响应速度来决定流量分配而不是把所有任务都压在一家模型上。比如在预算有限的情况下简单任务可以全部走 mini 型号复杂任务才调用大型模型整体成本会下降很多。6. 运行结果与效果验证6.1 运行命令在项目根目录下执行python examples/openai_demo.py python examples/anthropic_demo.py python examples/llm_gateway.py python examples/model_router.py如果你在编辑器里运行建议根据本机的 Python 解释器路径调整命令。6.2 预期输出示例openai_demo.py的预期输出类似大语言模型是一种基于深度学习技术通过大规模语料训练而成的自然语言处理模型能够理解和生成人类语言。anthropic_demo.py的预期输出类似大语言模型是一类在海量文本数据上预训练的神经网络模型具备理解语言、生成文本和执行多种任务的能力。不需要两家模型输出完全一致只需要确认能够正常获取回复即可。不同模型对同一个问题的表达方式本来就会有差异。6.3 如何判断调用成功判断成功的标准有三个程序没有抛异常。输出了文本内容而不是空的字符串。响应内容与问题相关而不是串到了别的对话。如果使用流式接口还需要在控制台看到持续的 token 增量输出。流式调用建议在测试阶段先关闭跑通后再启用否则排查问题时会多一层干扰。6.4 失败时第一步看哪里如果程序运行失败先按下面的顺序排查看错误类型是不是AuthenticationError/AuthenticationException。如果是说明 API Key 无效或权限不足。看是不是RateLimitError。如果是说明请求频率超过了账号配额等待一段时间后重试。看是不是APIConnectionError。如果是说明网络无法连通 API 服务需要检查网络配置。看是不是BadRequestError/APIStatusError。如果是通常是请求参数有问题检查model、messages、max_tokens等字段是否符合协议要求。不要一看到报错就盲目调整代码。先把完整错误日志读一遍绝大多数问题在错误提示里已经写清楚了。7. 常见问题与排查方法模型 API 接入过程中我们遇到过不少看起来奇怪、实际上原因很常规的问题。这里整理一份高频问题清单。问题现象可能原因排查方式解决方案报错 “Incorrect API key provided”API Key 填错或已过期检查 .env 文件中的 Key 是否完整复制重新生成 API Key 并更新配置报错 “model not found”当前账号没有该模型的访问权限或模型名称已更新登录平台后台查看可用模型列表换成有权限的模型或修改模型名称报错 “max_tokens is required”向 Anthropic 发送请求时没有提供 max_tokens检查请求参数Anthropic 请求必须显式传入 max_tokens报错 “The server had an error processing your request”API 服务临时异常查看服务状态页等待片刻重试实现重试机制设置退避时间请求超时网络不稳定或响应过长尝试减小输出长度检查网络连通性增加 timeout 参数或拆分长文本任务返回内容为空字符串模型生成了空内容或代码解析字段错误打印完整响应对象检查 content 列表结构正确取 text 字段接入兼容层后工具调用异常OpenAI 与 Anthropic 工具调用协议不一致打印工具调用前后的请求与响应在网关层分别实现两套工具解析逻辑提示 “unable to connect to anthropic services”网络无法连接到 API 域名检查防火墙、代理和 DNS 解析调整网络配置确认 API 域名在你的网络环境下可以访问提示 “failed to connect to api.anthropic.com”客户端无法建立 TLS 连接检查系统时间、证书配置和代理校准系统时间更新 CA 证书检查代理设置代码中集成多家 SDK 后依赖冲突SDK 之间传递依赖版本不兼容查看依赖树定位冲突包使用虚拟环境隔离或统一相关依赖版本针对“unable to connect to anthropic services”这类问题有一个容易被忽视的点某些网络代理工具会拦截 HTTPS 请求并抛出证书错误。如果你在本地设置了系统代理或终端代理且连接失败第一步不是改代码而是先暂时关闭代理测试直连是否正常。反过来如果你所在的企业网络本身限制了外部 API 访问就需要联系网络管理员确认是否需要配置白名单。8. 最佳实践与工程建议8.1 密钥与权限管理永远不要把 API Key 硬编码在代码里。团队协作项目使用.env文件加.gitignore是最低要求。更规范的做法是把 Key 放到公司内部的密钥管理平台应用启动时通过配置中心读取。给 API Key 设置最小权限如果某个 Key 只用于测试环境就不要给它生产环境的访问权限。定期轮换 Key 也是一个好习惯尤其是出现疑似泄露的情况时。8.2 模型的版本管理与可观测性模型名称会随着时间更新同一个模型名的行为也可能在厂商升级后发生变化。建议在配置文件中集中管理模型名称和版本而不是散落到各个业务类中。在请求和响应的关键节点打印日志记录模型名称、Token 消耗数量、响应耗时、错误信息。这样在模型升级后你可以快速对比同一个问题在不同模型版本下的表现。如果预算允许可以在关键业务上做 AB 对比先用 10% 流量走新模型验证效果后再放量。8.3 成本控制策略AI 应用的成本大头通常不是服务器而是模型 API 调用费。实际控制成本有几种常见手段使用更便宜的 mini 或轻量级模型处理简单任务。为每个任务设置max_tokens上限防止模型生成冗长无用的内容。对相似请求做结果缓存尤其是文档摘要、信息抽取这类重复度高的任务。批量任务使用异步队列而不是并发一次性发送大量请求。并发过高不仅容易触发限流还会让账单快速上升。8.4 生产环境的回滚与降级方案任何模型 API 都可能出现故障、限流或效果回退所以生产方案里必须包含降级逻辑。一个常见的做法是设置主模型和备选模型。主模型返回失败时网关层自动切换到备选模型。这个降级策略在逻辑上并不复杂核心就是把“模型选择”从硬编码变成配置可选。更进一步的方案是在关键链路上监测模型服务的可用性连续多次失败时触发熔断停止继续向故障提供商发送请求给服务恢复留出时间窗口。8.5 保持对底层平台的警惕与关注两家头部模型厂商的收入高度集中短期对开发者算是一件好事生态稳定、文档齐全、社区活跃。但从长期看技术选型上保持可替换性是每个 AI 应用开发者都需要掌握的工程素养。你在 OpenAI 上开发的工具调用逻辑最好也能在 Anthropic 上复用你在 Anthropic 上优化的长文档解析流程也要有机会迁移到其他平台。这种“厂家中立”的思想和当年 Java 开发者做数据库抽象、云厂商中立是同一个逻辑只不过今天换成了模型层。9. 总结与后续学习方向这篇文章从“70% of AI revenue comes from OpenAI and Anthropic”这一行业现象切入解释了为什么 AI 行业的大部分收入集中在模型层的头部玩家手里。对于开发者来说这个趋势最直接的影响不是你要不要学这两个平台而是你应该以什么样的工程方式来使用它们。文中给出了三个层次的示例直接用官方 SDK 调用 OpenAI、直接用官方 SDK 调用 Anthropic、通过网关层实现统一的模型接入。通过对比两个平台的 API 差异你应该能够理解模型切换这件事不应该靠临时改业务代码来实现而应该通过一层轻量的抽象来完成。这层抽象在项目初期可能只花一两天时间但它能为后续的模型选型、成本优化和故障降级省下大量时间。接下来可以继续深入的方向包括在网关层中加入流式响应的统一封装让两个平台都能以 Server-Sent Events 的方式向客户端推送内容。加入工具调用Function Calling / Tool Use的统一封装让 AI Agent 可以在两个平台上运行同一套工具集。引入模型评测机制对两个平台在具体业务任务上的回答质量做量化对比不再靠感觉选型。把网关层从单机 Python 类扩展成独立服务兼容更多厂商这样当开源模型或新兴模型服务成熟时你可以以更低的成本接入。模型 API 的格局不会一成不变今天 70% 的集中度也可能被新技术路线打破。但对普通开发者来说与其预测哪家公司会笑到最后不如把手里的代码写得足够解耦。这样无论行业怎么变化你都能快速适应。建议收藏本文下一次做 AI 应用技术选型时把文中的网关示例拿过来改一改直接作为新项目的起点。