前言
做 AI 应用最怕什么?供应商锁定。今天 OpenAI 涨价,明天某个国产模型效果更好,后天客户要求用私有化部署的模型……如果代码和某个 LLM 提供商深度耦合,每次切换都是一次重构。
SmartChat 通过一个 Provider 抽象层,实现了 7+ 个 LLM 提供商的无缝切换。来看看它是怎么设计的。
🔗 项目地址:smartchat.nofx.asia/
一、问题:LLM 提供商的碎片化
目前主流的 LLM 提供商各有各的 SDK 和 API 格式:
- OpenAI:
openaiSDK,/v1/chat/completions - Anthropic:
@anthropic-ai/sdk,/v1/messages,完全不同的消息格式 - 国产模型:大多兼容 OpenAI 格式,但 base URL 和模型名不同
如果每个提供商写一套调用逻辑,代码会变成这样:
// 反面教材:硬编码每个提供商
if (provider === 'openai') {
// OpenAI 的调用逻辑
} else if (provider === 'anthropic') {
// Anthropic 的调用逻辑
} else if (provider === 'deepseek') {
// DeepSeek 的调用逻辑
} // ... 无限 if-else
二、SmartChat 的 Provider 抽象层
SmartChat 的核心思路是:将所有提供商归为两类 SDK(OpenAI 和 Anthropic),通过预设配置 + 统一接口消除差异。
// Provider 预设配置
const PROVIDER_PRESETS = {
openai: {
baseURL: 'https://api.openai.com/v1',
models: ['gpt-4o', 'gpt-4o-mini', 'gpt-3.5-turbo'],
sdk: 'openai'
},
deepseek: {
baseURL: 'https://api.deepseek.com/v1',
models: ['deepseek-chat', 'deepseek-reasoner'],
sdk: 'openai' // DeepSeek 兼容 OpenAI 格式
},
qwen: {
baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
models: ['qwen-turbo', 'qwen-plus', 'qwen-max'],
sdk: 'openai' // 通义千问也兼容 OpenAI 格式
},
anthropic: {
baseURL: 'https://api.anthropic.com',
models: ['claude-3-5-sonnet', 'claude-3-haiku'],
sdk: 'anthropic'
},
custom: {
baseURL: '', // 用户自定义
models: [],
sdk: 'openai' // 默认走 OpenAI 兼容协议
}
};
关键洞察:绝大多数国产模型都兼容 OpenAI API 格式,所以只需要维护两套 SDK 调用逻辑(OpenAI 和 Anthropic),通过切换 baseURL 就能接入不同提供商。
三、统一的流式输出接口
不同 SDK 的流式输出格式差异很大,SmartChat 将其统一为一个 streamChat 函数:
async function streamChat(params: {
provider: string;
model: string;
messages: Message[];
apiKey: string;
temperature?: number;
}) {
const preset = PROVIDER_PRESETS[params.provider];
if (preset.sdk === 'openai') {
const client = new OpenAI({
apiKey: params.apiKey,
baseURL: preset.baseURL
});
return client.chat.completions.create({
model: params.model,
messages: params.messages,
temperature: params.temperature,
stream: true
});
} else if (preset.sdk === 'anthropic') {
const client = new Anthropic({ apiKey: params.apiKey });
return client.messages.stream({
model: params.model,
messages: convertToAnthropicFormat(params.messages),
max_tokens: 4096,
temperature: params.temperature
});
}
}
上层业务代码只需要调用 streamChat(),完全不关心底层用的是哪个提供商。

四、自定义端点:终极灵活性
SmartChat 还支持用户配置自定义的 OpenAI 兼容端点,这意味着可以接入:
- 本地部署的模型:Ollama、vLLM、LocalAI
- 企业私有化部署:Azure OpenAI、AWS Bedrock(通过兼容层)
- 任何 OpenAI 兼容的 API:各种代理、中转服务
用户只需在设置页面填入 base URL、API Key 和模型名称即可。
五、成本优化策略
多模型架构带来的一个隐藏好处是成本优化:
简单问题 → 使用便宜的模型(DeepSeek、Qwen-Turbo)
复杂问题 → 使用强力模型(GPT-4o、Claude Sonnet)
嵌入向量 → 使用本地模型(零成本)
每个机器人可以独立配置模型和参数,运营者可以根据业务场景灵活调整。
六、这个设计模式的可复用性
SmartChat 的 Provider 抽象层设计模式可以直接复用到其他 AI 应用中。核心思路总结:
- 识别 SDK 家族:大多数提供商属于 OpenAI 兼容或 Anthropic 两个家族
- 预设配置驱动:用配置而非代码来区分提供商
- 统一接口:上层业务只依赖抽象接口
- 自定义端点兜底:覆盖所有长尾场景
总结
LLM 领域变化太快,今天的最优选择明天可能就不是了。SmartChat 的多模型架构不是过度设计,而是对现实的务实应对。如果你也在做 AI 应用,强烈建议从第一天就做好 Provider 抽象。
🔗 项目地址:smartchat.nofx.asia/,MIT 开源协议。