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等事件类型。
因此,虽然可以通过兼容层做到“一套代码接两家”,但在真实项目中,我们还是建议先理解两者的原生差异,再决定要不要引入兼容方案。
下面用一张表格说明普通开发者最关心的基本差异:
| 对比项 | OpenAI | Anthropic |
|---|---|---|
| 官方 SDK | openai-python / openai-java | anthropic-sdk-python / anthropic-java |
| 核心接口 | Chat Completions API | Messages API |
| 系统提示词 | messages 列表中的 system role | 独立的 system 字段 |
| 必填参数 | model、messages | model、messages、max_tokens |
| 工具调用 | function_call / tools | tool_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 安装依赖
本文需要安装两个官方 SDK:
pip 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_KEY=sk-your-openai-key ANTHROPIC_API_KEY=sk-ant-your-anthropic-key这里有一个容易被忽略的安全问题。.env文件千万不要提交到 Git 仓库。如果你还没有创建.gitignore,请立即创建并加入.env:
.env venv/ __pycache__/API Key 属于敏感凭证。在团队协作或生产环境中,更建议使用专用的密钥管理服务,而不是直接写在环境变量文件里。关于这一点,后面的最佳实践章节会展开说明。
5. 完整示例:一套代码接入 OpenAI 和 Anthropic
5.1 最小示例:直接调用 OpenAI
先写一个最简单的对话调用,确认环境配置没有问题。
文件路径:examples/openai_demo.py
import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) def chat_with_openai(user_message: str) -> str: response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "你是一个简洁的技术助手。"}, {"role": "user", "content": user_message}, ], temperature=0.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,需要登录平台后台确认你的账号可以访问哪些模型。temperature=0.3用来控制输出随机性,数值越小,输出越稳定。- 实际项目中不要直接把 API Key 写在代码里。
5.2 最小示例:直接调用 Anthropic
Anthropic 的 Messages API 调用方式与 OpenAI 类似,但字段有差异。
文件路径:examples/anthropic_demo.py
import os from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) def chat_with_anthropic(user_message: str) -> str: message = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1024, 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.py
import 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_key=os.getenv("OPENAI_API_KEY")) self.anthropic_client = None elif backend == "anthropic": self.anthropic_client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) self.openai_client = None else: raise ValueError(f"Unsupported 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( model=self._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( model=self._model_map["anthropic"], max_tokens=1024, system=system_prompt, messages=[{"role": "user", "content": user_message}], ) return message.content[0].text if __name__ == "__main__": for backend in ["openai", "anthropic"]: gateway = LLMGateway(backend=backend) # 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.py
import os from anthropic import Anthropic from dotenv import load_dotenv from openai import OpenAI load_dotenv() openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) anthropic_client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) def summarize_with_claude(document: str) -> str: message = anthropic_client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=512, 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( model="gpt-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 应用技术选型时,把文中的网关示例拿过来改一改,直接作为新项目的起点。