本文分享一个基于 Spring Boot 3 的 AI 大模型开发框架,重点讲解如何通过通用兼容架构实现"一个模块接入10+大模型"的设计思路。

背景

在 Java 项目中接入 AI 大模型时,开发者通常面临以下问题:

  1. 每个大模型需要单独编写适配代码,维护成本高
  2. 不同模型的 API 格式差异大,切换模型需要重写业务逻辑
  3. 流式输出、工具调用、对话记忆等功能需要重复实现

基于这些问题,我设计了一个基于 OpenAI API 兼容标准 的通用架构,实现"配置即接入"的目标。
在这里插入图片描述

环境要求

  • Java 17+
  • Maven 3.6.3+
  • Spring Boot 3.2+

架构设计思路

核心问题

目前主流大模型(豆包、通义千问、智谱、Kimi、DeepSeek 等)都兼容 OpenAI API 规范,只是 baseUrl 和认证方式不同。

解决方案

采用"通用兼容 + 特殊适配"的设计模式:

  • 1 个通用模块 think-ai4j-provider-openai-compat 处理所有 OpenAI 兼容模型
  • 通过配置区分不同模型,无需编写额外代码
  • 特殊签名协议的模型(如腾讯 TC3-HMAC-SHA256)单独建模块

架构图

think-ai4j/
├── think-ai4j-core/                    # 核心模块:统一接口定义
├── think-ai4j-provider-openai-compat/  # 通用兼容模块:所有OpenAI格式模型
├── think-ai4j-memory/                  # 内存记忆
├── think-ai4j-memory-redis/            # Redis 持久化记忆
├── think-ai4j-tool/                    # 工具调用
├── think-ai4j-rag/                     # RAG 检索增强
├── think-ai4j-agent/                   # Agent 框架
├── think-ai4j-spring-boot-starter/     # Spring Boot 自动配置
└── think-ai4j-example/                 # 示例项目

核心接口设计

ChatProvider 接口

所有大模型 Provider 都实现统一的接口:

public interface ChatProvider {
    String getProviderName();
    AiResponse chat(ChatRequest request);
    Flux<String> stream(ChatRequest request);
}

业务代码只依赖接口,不依赖具体实现,实现模型自由切换。

通用兼容 Provider 实现

核心实现思路是:

  1. 从配置中读取 baseUrlapiKeymodel
  2. 构建标准 OpenAI 格式的 HTTP 请求
  3. 解析标准 OpenAI 格式的响应
public class OpenAiCompatProvider implements ChatProvider {
    
    private final String providerName;
    private final String baseUrl;
    private final String defaultModel;
    private final String apiKey;
    private final OkHttpClient httpClient;
    
    @Override
    public AiResponse chat(ChatRequest request) {
        String requestBody = buildRequestBody(request, false);
        Request httpRequest = new Request.Builder()
                .url(baseUrl + "/chat/completions")
                .header("Authorization", "Bearer " + apiKey)
                .post(RequestBody.create(requestBody, JSON))
                .build();
        
        try (Response response = httpClient.newCall(httpRequest).execute()) {
            return parseResponse(response.body().string());
        }
    }
}

HTTP 连接池优化

为了保证高性能,共享 OkHttp 连接池:

think:
  ai:
    compat:
      httpClient:
        connectionPool:
          max-idle-connections: 50
          keep-alive-minutes: 5
        timeout:
          connect-seconds: 30
          read-seconds: 60

Spring Boot 自动配置

通过 Spring Boot Starter 实现零配置集成:

@Configuration
@ConditionalOnClass(OpenAiCompatProvider.class)
@ConditionalOnProperty(prefix = "think.ai.compat", name = "providers")
static class OpenAiCompatAutoConfiguration {

    @Bean
    public List<ChatProvider> openAiCompatProviders(OpenAiCompatConfig config) {
        return config.getProviders().stream()
            .<ChatProvider>map(providerConfig -> 
                new OpenAiCompatProvider(providerConfig, config.getHttpClient()))
            .toList();
    }
}

配置文件中的每个 provider 自动注册为 Bean,并注入到 ChatProviderRegistry

实战接入

配置文件

think:
  ai:
    default-provider: doubao
    compat:
      providers:
        - name: doubao
          baseUrl: https://ark.cn-beijing.volces.com/api/v3
          apiKey: your-api-key
          model: ep-xxxxx

        - name: moonshot
          baseUrl: https://api.moonshot.cn/v1
          apiKey: your-api-key
          model: moonshot-v1-8k

    memory:
      type: memory
      max-messages: 20

新增模型只需加一段配置,无需改代码。

简单对话

@Autowired
private AiChat chat;

String result = chat.ask("你好");

带系统提示词

String result = chat.system("你是Java专家").ask("如何设计单例模式?");

流式输出

@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestParam String q) {
    return chat.stream(q);
}

切换模型

String result = chat.provider("glm").ask("你好");

进阶功能

工具调用(Function Calling)

通过 @AiTool 注解,让 AI 可以调用你的 Java 方法:

@Component
public class WeatherTool {

    @AiTool("查询天气")
    public String getWeather(@ToolParam(description = "城市名称") String city) {
        return "晴天,25度";
    }
}

框架会自动将方法元信息转换为 OpenAI 的 tool 格式,并处理调用流程。

对话记忆

支持内存记忆和 Redis 持久化记忆:

think:
  ai:
    memory:
      type: redis
      max-messages: 50
      ttl-minutes: 120
@Autowired
private ChatMemory memory;

memory.addMessage("user-123", AiMessage.user("我叫小明"));
List<AiMessage> history = memory.getMessages("user-123");

RAG 文档问答

@Autowired
private RagPipeline ragPipeline;

ragPipeline.ingest(List.of(
    new Document("公司规定年假为15天"),
    new Document("加班费按每小时100元计算")
));

String answer = ragPipeline.query("年假有多少天?");

Agent 智能代理

Agent agent = new Agent("助手", "你是一个专业的助手", chat)
    .addToolBean(new WeatherTool())
    .addToolBean(new SearchTool());

String result = agent.execute("北京天气如何?");

技术细节

流式输出实现

基于 OkHttp SSE + Reactor Flux 实现:

@Override
public Flux<String> stream(ChatRequest request) {
    return Flux.create(sink -> {
        EventSourceListener listener = new EventSourceListener() {
            @Override
            public void onEvent(EventSource eventSource, String id, String type, String data) {
                if ("[DONE]".equals(data)) {
                    sink.complete();
                    return;
                }
                JsonNode jsonNode = objectMapper.readTree(data);
                String content = jsonNode.get("choices").get(0).get("delta").get("content").asText();
                sink.next(content);
            }
        };
        EventSources.createFactory(httpClient).newEventSource(httpRequest, listener);
    });
}

错误处理

  • HTTP 异常:包装为 AiException,携带 provider 名称和错误码
  • 解析异常:记录日志并抛出详细错误信息
  • 流式失败:区分 response 为 null 和 t.getMessage() 的情况

空指针防护

在响应解析中增加多层 null 检查:

JsonNode contentNode = message.get("content");
if (contentNode != null && !contentNode.isNull()) {
    response.setContent(contentNode.asText());
}

总结

通过通用兼容架构,实现了:

  • 配置即接入:新增大模型只需改配置文件,无需编写代码
  • 接口统一:业务代码只依赖 AiChat 接口,不关心底层实现
  • 高性能:共享 OkHttp 连接池,可配置超时参数
  • 功能完整:支持同步对话、流式输出、工具调用、记忆、RAG、Agent

对于 Java 开发者来说,这种架构可以大大降低接入 AI 大模型的成本。

源码地址

  • Gitee: https://gitee.com/hongxinge/think-ai4j
  • GitHub: https://github.com/hongxinge/ThinkAi4j

代码已开源,欢迎交流讨论。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐