14. 如何设计一个支持多模型、多 Provider 的统一接入层?
整理多模型、多 Provider 统一接入层的架构设计与扩展策略。
简单回答
统一接入层的核心是定义一个标准化的内部 API 协议,然后为每个 Provider 实现一个适配器(Adapter),在适配器中处理请求/响应格式转换、认证、错误码映射和特性差异。关键挑战在于不同 Provider 的能力差异(工具调用格式、多模态支持、流式协议等)如何在统一接口中优雅处理。
详细解释
为什么需要统一接入层?
实际生产中,一个系统可能同时对接 OpenAI、Anthropic、Google、自建模型等多个 Provider。如果业务代码直接调用各家 SDK,代码中会充斥着 if provider == "openai" ... elif provider == "anthropic" ... 这种分支逻辑。新增或替换一个 Provider 需要改大量业务代码,维护成本很高。
统一接入层的目标是让业务层完全不感知底层 Provider 的差异,只和一个标准接口交互。
架构设计
核心是 Adapter 模式。定义一个内部标准协议(通常参考 OpenAI 的 Chat Completions API 格式,因为它已经成了事实标准),包括 messages 结构、tool 定义、response 格式等。然后为每个 Provider 写一个 Adapter,负责:
请求转换:把内部标准格式转成 Provider 的专有格式。比如 OpenAI 和 Anthropic 的 tool calling 格式不同、system message 的处理方式不同、多模态消息的图片编码方式不同。
响应转换:把 Provider 的响应转成内部标准格式。包括 content 字段提取、usage 统计映射、finish_reason 映射等。
流式适配:不同 Provider 的 SSE 数据格式不完全一样(字段名、事件格式、结束标记),Adapter 要做格式统一。
错误映射:不同 Provider 的错误码和错误信息各不相同,需要映射成统一的错误码体系。比如 OpenAI 返回 429 表示限流,Anthropic 返回 529 表示过载,都要映射成内部的"限流"错误。
认证管理:每个 Provider 的 API Key 管理方式不同(单 Key、组织 Key、OAuth 等),Adapter 统一处理。
能力差异处理
这是最难的部分。不同模型的能力不完全一致:有些支持 tool calling 有些不支持、有些支持多模态有些不支持、context window 长度不同、支持的参数不同(有些有 top_k 有些没有)。
处理方式通常是在模型注册表(Model Registry)中维护每个模型的能力矩阵:支持的功能列表、context window 大小、支持的参数列表、定价信息等。业务层在发请求前可以查询能力矩阵,确认目标模型是否支持需要的功能。如果不支持,可以选择降级处理(比如不支持 tool calling 的模型就不传 tools)或路由到其他模型。
SDK 设计
给业务层提供一个简洁的 SDK。使用方式类似:
底层自动选择对应的 Adapter、处理格式转换、管理认证。对业务方来说完全透明。
实际考量
版本管理要注意。各 Provider 的 API 会升级,新版本可能改变格式或行为。Adapter 需要做版本适配,能同时支持新旧版本的平滑过渡。
测试策略上,每个 Adapter 都需要有完善的集成测试。可以用 mock server 做本地测试,定期跑真实 Provider 的 smoke test 确保 Adapter 没有因为 Provider 端的变更而 broken。
已有方案
LiteLLM 是这个领域最成熟的开源方案,支持 100+ 模型的统一接口,基本可以开箱即用。如果业务场景比较标准,直接用 LiteLLM 比自建省很多工作。自建的优势是可以做更深度的定制——比如自定义路由逻辑、集成内部的认证系统和计费系统、处理特殊的业务格式等。
面试时可以这样答
统一接入层的核心设计是 Adapter 模式。定义一套内部标准协议——通常参考 OpenAI 的格式因为它已经是事实标准,然后为每个 Provider 实现一个 Adapter 做请求响应格式转换、认证管理和错误码映射。业务层只和标准接口交互,完全不感知底层 Provider。
最难处理的是能力差异。不同模型支持的功能不一致——tool calling 格式不同、有些支持多模态有些不支持、context window 大小不同。解决方式是维护一个 Model Registry,记录每个模型的能力矩阵,业务层发请求前可以查询。
流式输出的适配也是一个坑,各家的 SSE 格式不完全一样,需要在 Adapter 层统一。
开源方案中 LiteLLM 比较成熟,如果场景标准可以直接用。自建的优势是能做更深度的定制,比如和内部的路由、计费、认证系统集成。实际工程中很多团队是先用 LiteLLM 快速搭起来,后续再根据需要自建。
常见追问
- 不同 Provider 的 tool calling 格式差异具体有哪些?怎么做统一抽象?
- Provider 的 API 升级导致 Adapter 失效怎么处理?怎么做到灵活升级?
- 如果要支持自建的 vLLM 模型,Adapter 需要额外处理什么?