多模型 LLM Provider 抽象层
通过 Provider Adapter 模式统一管理多个大模型厂商的接口差异,实现参数映射、流式封装、路由和容错。
#tech / ai
#type / concept
#status / growing
[!info] related notes
- 所属 MOC: AI MOC
- 前置概念: Function Calling, LLM Task Routing
- 并列概念: Orchestration
- 关系笔记: AI 的能力以及对应的协议
多模型 LLM Provider 抽象层
一句话定义
多模型 LLM Provider 抽象层是用统一接口封装不同厂商(OpenAI、Claude、本地模型等)的 API 差异,让业务层不感知底层模型切换的一层架构设计。
核心机制 / 工作原理
统一接口定义
interface LLMProvider {
chat(input: ChatRequest): Promise<ChatResponse>;
stream(input: ChatRequest): AsyncIterable<ChatChunk>;
}
type ChatRequest = {
model: string;
messages: Message[];
temperature?: number;
maxTokens?: number;
tools?: ToolDefinition[];
stream?: boolean;
};
type ChatResponse = {
id: string;
content: string;
finishReason: string;
usage: TokenUsage;
};
type ChatChunk = {
id: string;
delta: string;
finishReason?: string;
usage?: TokenUsage;
};
Provider Adapter 每个厂商一个实现
OpenAIProvider— 处理 OpenAI 的 API 格式ClaudeProvider— 处理 Anthropic 的 API 格式LocalModelProvider— 处理 Ollama / vLLM 等本地模型
每个 adapter 内部负责:
- 参数字段映射(如
maxTokens→max_tokens、max_completion_tokens) - 认证方式差异(API key、OAuth、bearer token)
- 流式 chunk 格式解析(SSE、WebSocket、NDJSON)
- 错误码映射
参数适配
不同厂商的同名参数语义可能不同,需要做映射:
| 统一字段 | OpenAI | Claude | 本地模型 |
|---|---|---|---|
| temperature | temperature | temperature | temperature |
| maxTokens | max_tokens | max_tokens | num_predict |
| stream | stream: true | stream: true | stream: true |
对于语义不同的参数(如 Claude 的 top_k),在 adapter 内部做转换。
Router 层
在 provider 之上加一层路由:
- 按能力路由:是否支持 function calling、vision、长上下文
- 按成本路由:简单任务走便宜模型,复杂任务走强模型
- 按可用性路由:失败自动 fallback 到备用模型
- 按租户配置路由:不同用户使用不同 key 或模型
容错与统计
- 统一错误格式:所有 provider 的错误都映射为标准错误码
- 重试与 fallback:主模型超时或限流时自动切换
- usage 统计:统一记录 token 消耗,用于成本分析
最小例子 / 最小场景
业务代码只写一次:
const provider = getProvider('openai');
const response = await provider.chat({
model: 'gpt-4o',
messages: [{ role: 'user', content: '你好' }],
temperature: 0.7,
});
切换到 Claude 只改配置,不改业务代码:
const provider = getProvider('claude');
边界与常见误解
- 不是所有差异都能在 adapter 层抹平;function calling 格式、system message 处理方式、context window 大小差异需要业务层感知
- “用现成库”是合理选择(如 Vercel AI SDK、LiteLLM),但要理解它们背后的抽象原理
- 流式 chunk 的粒度和时机各厂商不同,统一
ChatChunk只是格式统一,不能保证语义完全一致 - 成本计算不能简单比较 token 数,因为不同模型的 tokenizer 不同