RAG/Agent大模型通用对接框架
如何设计一个通用的大模型对接框架
基于企业级 RAG 项目实战,设计一个支持多供应商、自动容错、易扩展的 LLM 对接架构
一、背景与挑战
在企业级 AI 应用开发中,我们经常面临以下挑战:
-
多供应商接入:需要同时支持阿里云百炼、硅基流动、Ollama 本地模型等多种 LLM 供应商
-
稳定性要求:单个模型故障不能影响整体服务
-
成本控制:需要根据场景智能选择不同价位的模型
-
快速扩展:新增供应商时不应修改现有业务代码
-
统一体验:业务层无需关心底层调用细节
本文基于一个生产级 RAG(检索增强生成)项目,详细介绍如何设计一个通用的大模型对接框架。
二、架构设计概览
2.1 整体架构图
┌─────────────────────────────────────────────────────────────┐ │ 业务层 (Business Layer) │ │ ChatController / Service │ └─────────────────────────────┬───────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ RoutingLLMService (路由服务) │ │ • 统一入口 • 故障转移 • 健康检查 • 流式首包探测 │ └─────────────────────────────┬───────────────────────────────┘ │ ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ ModelSelector │ │ ModelRouting │ │ ModelHealth │ │ (模型选择器) │ │ Executor (执行器) │ │ Store (健康存储) │ └──────────────────┘ └──────────────────┘ └──────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ ChatClient 接口 (策略模式) │ ├──────────────────┬──────────────────┬──────────────────────┤ │ BaiLianChatClient│ SiliconFlowClient│ OllamaChatClient │ │ (阿里云百炼) │ (硅基流动) │ (本地模型) │ └──────────────────┴──────────────────┴──────────────────────┘
2.2 核心设计原则
| 原则 | 说明 |
|---|---|
| 接口隔离 | 业务代码只依赖抽象接口,不感知具体实现 |
| 配置驱动 | 所有供应商和模型通过配置管理,零代码修改 |
| 自动容错 | 故障自动转移,无需业务层处理 |
| 健康感知 | 熔断机制避免连续请求故障模型 |
| 开闭原则 | 对扩展开放,对修改关闭 |
三、核心组件实现
3.1 定义统一接口
/**
* 聊天客户端接口 - 所有 LLM 供应商的统一抽象
*/
public interface ChatClient {
/**
* 获取服务提供商名称
*/
String provider();
/**
* 同步聊天方法
*/
String chat(ChatRequest request, ModelTarget target);
/**
* 流式聊天方法
*/
StreamCancellationHandle streamChat(
ChatRequest request,
StreamCallback callback,
ModelTarget target
);
}
设计要点:
-
provider()方法用于标识供应商,支持路由分发 -
同步和流式两种调用方式,覆盖不同场景
-
ModelTarget封装目标模型信息,实现参数透传
3.2 路由服务:统一入口
@Slf4j
@Service
@Primary // 标记为主要实现,注入时优先使用
public class RoutingLLMService implements LLMService {
private final ModelSelector selector;
private final ModelRoutingExecutor executor;
private final Map<String, ChatClient> clientsByProvider;
// Spring 自动注入所有 ChatClient 实现
public RoutingLLMService(
ModelSelector selector,
ModelRoutingExecutor executor,
List<ChatClient> clients) {
this.selector = selector;
this.executor = executor;
this.clientsByProvider = clients.stream()
.collect(Collectors.toMap(ChatClient::provider, Function.identity()));
}
@Override
public String chat(ChatRequest request) {
return executor.executeWithFallback(
ModelCapability.CHAT,
selector.selectChatCandidates(request.getThinking()),
target -> clientsByProvider.get(target.candidate().getProvider()),
(client, target) -> client.chat(request, target)
);
}
@Override
public StreamCancellationHandle streamChat(ChatRequest request, StreamCallback callback) {
List<ModelTarget> targets = selector.selectChatCandidates(request.getThinking());
// ... 流式调用逻辑
}
}
核心能力:
-
通过构造函数自动收集所有
ChatClient实现 -
委托给
ModelSelector选择候选模型列表 -
委托给
ModelRoutingExecutor执行故障转移
3.3 模型选择器:智能调度
@Component
public class ModelSelector {
private final AIModelProperties properties;
private final ModelHealthStore healthStore;
public List<ModelTarget> selectChatCandidates(Boolean deepThinking) {
AIModelProperties.ModelGroup group = properties.getChat();
// 1. 根据是否深度思考选择首选模型
String firstChoiceModelId = resolveFirstChoiceModel(group, deepThinking);
// 2. 过滤并排序候选列表
List<AIModelProperties.ModelCandidate> enabled = candidates.stream()
.filter(c -> c != null && !Boolean.FALSE.equals(c.getEnabled()))
.filter(c -> !Boolean.TRUE.equals(deepThinking)
|| Boolean.TRUE.equals(c.getSupportsThinking()))
.sorted(Comparator.comparing(AIModelProperties.ModelCandidate::getPriority)
.thenComparing(AIModelProperties.ModelCandidate::getId))
.collect(Collectors.toList());
// 3. 将首选模型提升到第一位
promoteFirstChoiceModel(enabled, firstChoiceModelId);
// 4. 构建目标列表,过滤熔断状态的模型
return buildAvailableTargets(enabled);
}
}
调度策略:
-
支持深度思考模式智能匹配
-
按优先级排序
-
自动过滤熔断中的模型
3.4 路由执行器:故障转移
@Component
public class ModelRoutingExecutor {
private final ModelHealthStore healthStore;
public <C, T> T executeWithFallback(
ModelCapability capability,
List<ModelTarget> targets,
Function<ModelTarget, C> clientResolver,
ModelCaller<C, T> caller) {
Throwable last = null;
for (ModelTarget target : targets) {
C client = clientResolver.apply(target);
if (client == null) {
continue;
}
// 检查熔断状态
if (!healthStore.allowCall(target.id())) {
continue;
}
try {
T response = caller.call(client, target);
healthStore.markSuccess(target.id()); // 标记成功
return response;
} catch (Exception e) {
last = e;
healthStore.markFailure(target.id()); // 标记失败
log.warn("模型调用失败,切换下一个:modelId={}", target.id(), e);
}
}
throw new RemoteException("所有候选模型均调用失败", last);
}
}
容错机制:
-
遍历候选列表,逐个尝试
-
成功则立即返回,失败则切换下一个
-
实时更新健康状态
3.5 健康存储:熔断器
@Component
public class ModelHealthStore {
private final ConcurrentHashMap<String, CircuitBreaker> breakers = new ConcurrentHashMap<>();
private final int failureThreshold;
private final long openDurationMs;
public boolean allowCall(String modelId) {
CircuitBreaker breaker = getOrCreate(modelId);
return breaker.allowCall();
}
public void markSuccess(String modelId) {
getOrCreate(modelId).markSuccess();
}
public void markFailure(String modelId) {
getOrCreate(modelId).markFailure();
}
private static class CircuitBreaker {
private int failureCount = 0;
private long openUntil = 0;
synchronized boolean allowCall() {
if (openUntil > System.currentTimeMillis()) {
return false; // 熔断开启中
}
if (openUntil > 0) {
// 半开状态,允许一次探测
openUntil = 0;
failureCount = 0;
}
return true;
}
synchronized void markSuccess() {
failureCount = 0;
}
synchronized void markFailure() {
failureCount++;
if (failureCount >= failureThreshold) {
openUntil = System.currentTimeMillis() + openDurationMs;
}
}
}
}
熔断策略:
-
连续失败 N 次触发熔断
-
熔断期间拒绝请求
-
超时后进入半开状态探测
四、供应商实现示例
4.1 阿里云百炼实现
@Slf4j
@Service
@RequiredArgsConstructor
public class BaiLianChatClient implements ChatClient {
private final OkHttpClient httpClient;
private final Executor modelStreamExecutor;
private final Gson gson = new Gson();
@Override
public String provider() {
return ModelProvider.BAI_LIAN.getId();
}
@Override
public String chat(ChatRequest request, ModelTarget target) {
// 1. 获取提供商配置
AIModelProperties.ProviderConfig provider = requireProvider(target);
// 2. 构建请求体
JsonObject reqBody = buildRequestBody(request, target, false);
// 3. 发送 HTTP 请求
Request httpRequest = new Request.Builder()
.url(resolveUrl(provider, target))
.post(RequestBody.create(reqBody.toString(), HttpMediaTypes.JSON))
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer " + provider.getApiKey())
.build();
try (Response response = httpClient.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) {
throw new ModelClientException("请求失败", response.code());
}
return extractChatContent(parseJsonBody(response.body()));
}
}
@Override
public StreamCancellationHandle streamChat(
ChatRequest request,
StreamCallback callback,
ModelTarget target) {
Call call = httpClient.newCall(buildStreamRequest(request, target));
return StreamAsyncExecutor.submit(
modelStreamExecutor,
call,
callback,
cancelled -> doStream(call, callback, cancelled)
);
}
}
4.2 硅基流动实现(OpenAI 兼容接口)
@Slf4j
@Service
@RequiredArgsConstructor
public class SiliconFlowChatClient implements ChatClient {
// 结构与 BaiLianChatClient 几乎一致
// 主要差异在于 API 端点和响应解析格式
@Override
public String provider() {
return ModelProvider.SILICON_FLOW.getId();
}
// ... 实现细节类似
}
五、配置管理
5.1 配置类设计
@Data
@Configuration
@ConfigurationProperties(prefix = "ai")
public class AIModelProperties {
/** 提供商配置 */
private Map<String, ProviderConfig> providers = new HashMap<>();
/** 聊天模型组 */
private ModelGroup chat = new ModelGroup();
/** Embedding 模型组 */
private ModelGroup embedding = new ModelGroup();
@Data
public static class ProviderConfig {
private String url;
private String apiKey;
private Map<String, String> endpoints = new HashMap<>();
}
@Data
public static class ModelGroup {
private String defaultModel;
private String deepThinkingModel;
private List<ModelCandidate> candidates = new ArrayList<>();
}
@Data
public static class ModelCandidate {
private String id; // 模型标识
private String provider; // 对应 providers 的 key
private String model; // 实际 API 模型名
private Integer priority = 100; // 优先级
private Boolean enabled = true; // 是否启用
private Boolean supportsThinking = false; // 是否支持思考链
}
}
5.2 配置文件示例
ai: # 提供商配置 providers: bailian: url: https://dashscope.aliyuncs.com api-key: sk-your-api-key endpoints: chat: /compatible-mode/v1/chat/completions siliconflow: url: https://api.siliconflow.cn api-key: sk-your-api-key endpoints: chat: /v1/chat/completions ollama: url: http://localhost:11434 endpoints: chat: /api/chat # 路由策略 selection: failure-threshold: 2 # 失败阈值 open-duration-ms: 30000 # 熔断时长 # 聊天模型配置 chat: default-model: qwen3-max deep-thinking-model: qwen3-max candidates: - id: glm-4.7 provider: siliconflow model: Pro/zai-org/GLM-4.7 supports-thinking: true priority: 0 # 最高优先级 - id: qwen-plus provider: bailian model: qwen-plus-latest priority: 1 - id: qwen3-local provider: ollama model: qwen3:8b-fp16 priority: 2
六、如何扩展新供应商
6.1 三步接入新供应商
步骤 1:在 ModelProvider 枚举中添加
public enum ModelProvider {
BAI_LIAN("bailian"),
SILICON_FLOW("siliconflow"),
OLLAMA("ollama"),
OPENAI("openai"); // 新增
private final String id;
// ...
}
步骤 2:实现 ChatClient 接口
@Slf4j
@Service
@RequiredArgsConstructor
public class OpenAIChatClient implements ChatClient {
private final OkHttpClient httpClient;
@Qualifier("modelStreamExecutor")
private final Executor modelStreamExecutor;
@Override
public String provider() {
return ModelProvider.OPENAI.getId();
}
@Override
public String chat(ChatRequest request, ModelTarget target) {
// 实现 HTTP 调用逻辑
}
@Override
public StreamCancellationHandle streamChat(
ChatRequest request,
StreamCallback callback,
ModelTarget target) {
// 实现流式调用逻辑
}
}
步骤 3:添加配置
ai: providers: openai: url: https://api.openai.com api-key: sk-your-key endpoints: chat: /v1/chat/completions chat: candidates: - id: gpt-4o provider: openai model: gpt-4o priority: 1
七、架构亮点总结
| 特性 | 实现方式 | 收益 |
|---|---|---|
| 统一接口 | ChatClient 接口 |
业务层零感知 |
| 自动容错 | ModelRoutingExecutor |
服务高可用 |
| 智能路由 | ModelSelector + 优先级 |
成本最优化 |
| 熔断保护 | ModelHealthStore |
避免雪崩 |
| 配置驱动 | AIModelProperties |
零代码变更 |
| 快速扩展 | Spring 自动发现 | 新增供应商仅需 3 步 |
八、适用场景
本架构适用于以下场景:
-
企业级 AI 应用:需要同时对接多个 LLM 供应商
-
RAG 系统:需要智能选择 Embedding、Rerank、Chat 模型
-
成本敏感场景:需要根据优先级自动选择性价比最优的模型
-
高可用要求:单点故障不能影响整体服务
-
快速迭代:需要频繁接入新的 LLM 供
九、总结
本文介绍了一种通用的大模型对接框架设计,核心思想是:
-
接口抽象:用统一的接口屏蔽供应商差异
-
配置驱动:用配置代替硬编码,实现灵活调度
-
自动容错:内置故障转移和熔断机制
-
开闭原则:扩展新供应商无需修改现有代码
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)