AI 大模型统一集成|如何封装多个大模型 API 调用

🌟 在这系列文章中,我们将一起探索如何搭建一个支持大模型集成项目 ChatAI 的开发过程,从 架构设计代码实战,逐步搭建一个支持 多种大模型(GPT-4、DeepSeek 等)一站式大模型集成与管理平台,并集成 认证中心、微服务、流式对话 等核心功能。

🔍 从架构设计到代码实现,一起探讨如何应对不同技术挑战,最终打造出高效、可扩展的大模型平台,目前项目基础架构已经搭建完成。

系列目录规划:

  1. ChatAI:从零开始打造你的专属大模型集成平台
  2. Spring Boot + OpenAI/DeepSeek:如何封装多个大模型 API 调用
  3. 微服务 + 认证中心:如何保障大模型 API 的安全调用
  4. 支持流式对话 SSE & WebSocket:让 AI 互动更丝滑
  5. 缓存与性能优化:提高 LLM API 响应速度
  6. 开源部署指南(Docker)

第二篇:Spring Boot + OpenAI/DeepSeek:如何封装多个大模型 API 调用

🎯 如何让你的项目支持 OpenAI、DeepSeek、本地大模型等多种 LLM?
🎯 如何封装 API,做到扩展性强、调用方便?
🎯 这篇文章带你一步步搭建通用 LLM 调用服务!

为什么要封装 LLM API?

在大模型开发中,我们往往需要 支持多个模型,例如:

  • GPT-4(OpenAI) :行业最强模型之一,但 API 价格较贵
  • DeepSeek:性价比高,部分场景效果接近 GPT-4
  • 本地大模型(如 ChatGLM) :适合私有化部署,数据安全

如果在代码里直接写多个 API 请求,会导致 代码冗余、扩展性差。我们需要一个 统一封装的 LLM API 调用层,让项目可以随时切换模型,甚至同时支持多个模型。

效果展示

在这里插入图片描述
DeepSeek API 调用交互稍微有点点耗时…目前还没有支持流式输出效果(下一期优化),代码仓库地址:https://github.com/pitt1997/ChatAI

代码实现

实现简单的 AI 接口调用还是比较简单,定义接口和具体接口的调用逻辑即可,下面是代码演示。

在这里插入图片描述

1)Controller 层

ChatController 定义一个页面的路由地址

@RestController
public class ChatController {

    /**
     * chat页面
     */
    @GetMapping("/auth/chat")
    public ModelAndView chat(ModelAndView modelAndView) {
        modelAndView.setViewName("ftl/chat");
        return modelAndView;
    }
}

ChatApiController 定义一个 API 交互接口。

@RestController
@RequestMapping("/api/ai")
public class ChatApiController {

    @Autowired
    private ChatService chatService;

    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    @PostMapping("/chat")
    public ResponseEntity<String> chat(@RequestBody ChatRequest request, @RequestHeader("Authorization") String token) {
        // TODO 测试放行(后续加上JWT票据认证)
        if (token.startsWith("Bearer ")) {
            return ResponseEntity.ok(chatService.callAIModel(request.getMessage(), request.getModelType()));
        }
        // 认证中心解析 JWT 验证权限
        SessionUser sessionUser = jwtTokenProvider.validateUserToken(token);
        if (sessionUser == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
        }
        return ResponseEntity.ok(chatService.callAIModel(request.getMessage(), request.getModelType()));
    }
}
2)VO 层

请求对象,主要定义输入的消息和模型的类型。

@Data
public class ChatRequest {

    private String message;   // 用户输入的消息

    private String modelType; // 选择的大模型,例如 "chatgpt" 或 "local"
}
3)Service 层

这里封装不同模型的调用实现。

@Service
public class ChatService {

    @Autowired
    private OpenAIClient openAIClient;

    @Autowired
    private DeepSeekClient deepSeekClient;

    @Autowired
    private LocalLLMClient localLLMClient;

    public String callAIModel(String prompt, String modelType) {
        if ("chatgpt".equalsIgnoreCase(modelType)) {
            return openAIClient.chat(prompt);
        } else if ("deepseek".equalsIgnoreCase(modelType)) {
            return deepSeekClient.chat(prompt);
        } else if ("local".equalsIgnoreCase(modelType)) {
            return localLLMClient.chat(prompt);
        }
        return "Invalid Model Type";
    }
}

4)调用大模型接口 API

实现具体大模型的 API 调用逻辑。以 DeepSeek 为例,注意 DeepSeek 需要提前在官网注册密钥。(注:按照官网要求的请求参数格式进行请求即可,注意需要正确解析返回结果中的内容)。

@Component
public class DeepSeekClient {
    private static final String API_URL = "https://api.deepseek.com/chat/completions"; // DeepSeek API 地址
    private static final String API_KEY = "你的 DeepSeek API Key"; // 替换为你的 API Key
    private static final String MODEL = "deepseek-chat"; // deepseek-v3 / deepseek-r1

    public String chat(String prompt) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Bearer " + API_KEY);

        Map<String, Object> body = new HashMap<>();
        body.put("model", MODEL); // deepseek-v3 / deepseek-r1
        body.put("temperature", 0.7); // 可调整温度
        body.put("max_tokens", 2048); // 控制回复长度

        List<Map<String, String>> messages = Arrays.asList(
                new HashMap<String, String>() {{
                    put("role", "user");
                    put("content", prompt);
                }}
        );
        body.put("messages", messages);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = restTemplate.exchange(API_URL, HttpMethod.POST, request, String.class);

        return extractContent(response.getBody());
    }

    // 解析一下大模型返回结果的json参数。
    private String extractContent(String responseBody) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode root = objectMapper.readTree(responseBody);
            return root.path("choices").get(0).path("message").path("content").asText();
        } catch (Exception e) {
            e.printStackTrace();
            return "Error parsing response";
        }
    }
}

OpenAI 调用逻辑基本一致。

@Component
public class OpenAIClient {
    private static final String API_URL = "https://api.openai.com/v1/chat/completions";
    private static final String API_KEY = "你的 OpenAI API Key"; // 请替换为你的 API Key

    public String chat(String prompt) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Bearer " + API_KEY);

        Map<String, Object> body = new HashMap<>();
        body.put("model", "gpt-4");

        List<Map<String, String>> messages = Arrays.asList(
                new HashMap<String, String>() {{
                    put("role", "user");
                    put("content", prompt);
                }}
        );
        body.put("messages", messages);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = restTemplate.exchange(API_URL, HttpMethod.POST, request, String.class);

        return response.getBody();
    }
}

5)调用本地模型

也可以调用本地部署的大模型(需要提前部署本地大模型,可以看我之前的文章部署方法)。

@Component
public class LocalLLMClient {

    private static final String LOCAL_MODEL_URL = "http://localhost:5000/api/chat";

    public String chat(String prompt) {
        RestTemplate restTemplate = new RestTemplate();

        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("prompt", prompt);

        ResponseEntity<String> response = restTemplate.postForEntity(LOCAL_MODEL_URL, requestBody, String.class);
        return response.getBody();
    }
}


6)前端页面(HTML + JavaScript)

一个简单的 HTML 页面,输入问题后,调用后端 API 获取大模型的回答(暂时使用 HTML 做一个演示)。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>AI 聊天</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: #f4f4f4;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        .chat-container {
            width: 500px;
            background: #fff;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
        }
        h1 {
            text-align: center;
            color: #333;
        }
        .input-group {
            margin: 15px 0;
        }
        input, select, button {
            width: 100%;
            padding: 10px;
            margin-top: 5px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
        button {
            background: #007bff;
            color: white;
            cursor: pointer;
        }
        button:hover {
            background: #0056b3;
        }
        .response {
            margin-top: 20px;
            background: #eef;
            padding: 10px;
            border-radius: 5px;
            min-height: 50px;
        }
    </style>
</head>
<body>
<div class="chat-container">
    <h1>大模型 AI 聊天</h1>
    <div class="input-group">
        <label>输入你的问题:</label>
        <input type="text" id="message" placeholder="请输入问题">
    </div>
    <div class="input-group">
        <label>选择模型:</label>
        <select id="modelType">
            <option value="chatgpt">ChatGPT</option>
            <option value="deepseek">DeepSeek</option>
            <option value="local">本地模型</option>
        </select>
    </div>
    <button onclick="sendMessage()">发送</button>
    <div class="response" id="response">AI 回复将在这里显示...</div>
</div>

<script>
    async function sendMessage() {
        const message = document.getElementById('message').value;
        const modelType = document.getElementById('modelType').value;
        // 你的 JWT 令牌
        const token = getCookie('JSESSIONID'); // 这里应从登录系统获取
        console.log('JWT Token:', token); // 打印 token 值
        const response = await fetch('/web/api/ai/chat', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer B6FC7391D7856A16391F9860DA5DA3B8}`
            },
            body: JSON.stringify({ message, modelType })
        });
        const text = await response.text();
        document.getElementById('response').innerText = text;
    }

    function getCookie(name) {
        const cookies = document.cookie.split(';');
        for (let cookie of cookies) {
            const [cookieName, cookieValue] = cookie.trim().split('=');
            if (cookieName === name) {
                return decodeURIComponent(cookieValue);
            }
        }
        return null;
    }
</script>
</body>
</html>


7) 认证中心(JWT 解析示例)

接口调用时应当校验当前用户的票据(登录时会存储用户会话票据信息)。

        // 认证中心解析 JWT 验证权限
        SessionUser sessionUser = jwtTokenProvider.validateUserToken(token);
        if (sessionUser == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
        }

效果测试

🔥 现在,你的 AI 聊天前后端已完成!

  1. 直接访问登录 http://localhost:8080/web/auth/login 页面
  2. 输出用户名/密码:admin/123456
  3. 跳转大模型页面,选择对应大模型,开始对话

总结

  • 架构:微服务 + 认证中心 + API 网关 + 本地/远程大模型
  • Java 代码:完整的 Controller、Service、API 调用示例
  • 前端:简单 HTML + JS 渲染
  • 认证:JWT 校验

这样,你的系统可以支持用户认证,并调用本地或第三方大模型进行 AI 交互。

结语

本篇文章,我们介绍了 如何封装多个 LLM(大模型) API 调用

但是,目前的 对话是一次性返回的,后续我们将完善 微服务 + 认证中心:如何保障大模型 API 的安全调用, 并且支持流式对话(SSE)增加 WebSocket 实时消息实现 实时输出 AI 回复!敬请期待!

📌 下一章预告:SSE + WebSocket 实现流式对话!


📢 你对这个项目感兴趣吗?欢迎 Star & 关注! 📌 GitHub 项目地址 📢 详细部署教程视频已更新

### 如何通过 Java 调用 DeepSeek 大模型实现连续对话 为了在 Java 中调用 DeepSeek大模型并实现连续对话功能,可以按照以下方法构建代码逻辑。这涉及设置 HTTP 请求、传递必要的参数以及解析返回的结果。 #### 1. 开发环境准备 确保已安装 JDK 并配置好 Maven 或 Gradle 构建工具来管理依赖项。此外,需引入 `HttpClient` 库用于发送网络请求[^1]。 ```xml <!-- 如果使用Maven, 添加以下依赖 --> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2</version> </dependency> ``` --- #### 2. 获取 API Key 和 URL 地址 前往 [DeepSeek 官网](https://www.deepseek.com/) 注册账户并申请有效的 API 密钥。API 访问地址通常类似于 `https://api.deepseek.com/v1/completions`。 --- #### 3. 示例代码:Java 实现连续对话 以下是完整的 Java 示例代码,展示如何利用 DeepSeek API 创建一个简单的客户端程序以支持多轮会话: ```java import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.io.entity.StringEntity; public class DeepSeekChat { private static final String DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat"; private static final String YOUR_DEEPSEEK_API_KEY = "your_api_key_here"; public static void main(String[] args) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { // 初始化历史记录列表 StringBuilder conversationHistory = new StringBuilder(); while (true) { System.out.println("请输入您的问题(输入 'exit' 结束):"); java.util.Scanner scanner = new Scanner(System.in); String userInput = scanner.nextLine(); if ("exit".equalsIgnoreCase(userInput)) break; // 将用户的输入追加到历史记录中 conversationHistory.append("User: ").append(userInput).append("\n"); // 准备 JSON 数据结构作为 POST 请求体 String requestBodyJson = "{" + "\"model\": \"deepseek-chat-xxl\", " + "\"messages\": [{\"role\": \"user\",\"content\": \"" + userInput + "\"}], " + "\"max_tokens\": 100," + "\"temperature\": 0.7" + "}"; HttpPost postRequest = new HttpPost(DEEPSEEK_API_URL); // 设置请求头部信息 postRequest.setHeader("Authorization", "Bearer " + YOUR_DEEPSEEK_API_KEY); postRequest.setHeader("Content-Type", ContentType.APPLICATION_JSON.toString()); postRequest.setEntity(new StringEntity(requestBodyJson)); CloseableHttpResponse response = httpClient.execute(postRequest); // 解析服务器响应数据 int statusCode = response.getCode(); if (statusCode == 200){ String responseBody = org.apache.commons.io.IOUtils.toString(response.getEntity().getContent(), "UTF-8"); // 提取 AI 返回的内容,并更新聊天历史 String aiResponse = parseAIResponseFromJSON(responseBody); conversationHistory.append("Assistant: ").append(aiResponse).append("\n"); System.out.println("AI的回答:" + aiResponse); }else{ System.err.println("Error occurred during request processing."); } response.close(); } } catch (Exception e) { e.printStackTrace(); } } /** * 假设我们有一个辅助函数用来提取 JSON 字符串中的实际回复部分。 */ private static String parseAIResponseFromJSON(String jsonResponseText){ // 使用正则表达式或其他方式解析 JSON return jsonResponseText.contains("\"content\":\"") ? jsonResponseText.split("\"content\":\"")[1].split("\"")[0] : ""; } } ``` 上述代码实现了基本的循环机制,在每次迭代过程中收集用户提问并将它们附加至上下文中再提交给 DeepSeek 模型处理。 --- #### 4. 关键点解释 - **请求头**:需要指定 `"Authorization"` 来验证身份,同时定义 `"Content-Type": application/json` 表明传输的是 JSON 格式的正文内容。 - **消息格式化**:对于每一轮新的交互,都应重新构造包含当前回合的消息对象数组 `{ role: user|assistant , content}` ,以便维持连贯性。 - **错误处理**:当遇到异常情况时应当妥善捕获并反馈具体原因给前端使用者知道哪里出了差错。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值