【大模型统一集成项目】如何封装多个大模型 API 调用

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

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

系列目录规划:

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

代码实现

实现简单的 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 {@Autowiredprivate ChatService chatService;@Autowiredprivate 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 {@Autowiredprivate OpenAIClient openAIClient;@Autowiredprivate DeepSeekClient deepSeekClient;@Autowiredprivate 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 Keyprivate static final String MODEL = "deepseek-chat"; // deepseek-v3 / deepseek-r1public 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-r1body.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 Keypublic 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();}
}

3. 前端页面(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>

4. 认证中心(JWT 解析示例)

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

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

5. 效果测试

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

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

6. 总结

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

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

结语

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

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

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


📢 你对这个项目感兴趣吗?欢迎 Star & 关注! 📌 GitHub 项目地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI4CODE】3 Trae 锤一个贪吃蛇的小游戏

【AI4CODE】目录 【AI4CODE】1 Trae CN 锥安装配置与迁移 【AI4CODE】2 Trae 锤一个 To-Do-List 这次还是采用 HTML/CSS/JAVASCRIPT 技术栈 Trae 锤一个贪吃蛇的小游戏。 1 环境准备 创建一个 Snake 的子文件夹&#xff0c;清除以前的会话记录。 2 开始构建 2.1 输入会…

【简答题002】Java变量简答题

博主会经常补充完善这里面问题的答案。希望可以得到大家的一键三连支持&#xff0c;你的鼓励是我坚持下去的最大动力&#xff01;谢谢&#xff01; 001 什么是Java变量&#xff1f; Java变量是用来存储数据并在程序中引用的命名空间。 002 Java变量有哪些类型&#xff1f; J…

从零开发Chrome广告拦截插件:开发、打包到发布全攻略

从零开发Chrome广告拦截插件&#xff1a;开发、打包到发布全攻略 想打造一个属于自己的Chrome插件&#xff0c;既能拦截烦人的广告&#xff0c;又能优雅地发布到Chrome Web Store&#xff1f;别担心&#xff0c;这篇教程将带你从零开始&#xff0c;动手开发一个功能强大且美观…

基于腾讯云高性能HAI-CPU的跨境电商客服助手全链路解析

跨境电商的背景以及痛点 根据Statista数据&#xff0c;2025年全球跨境电商市场规模预计达6.57万亿美元&#xff0c;年增长率保持在12.5% 。随着平台规则趋严&#xff08;如亚马逊封店潮&#xff09;&#xff0c;更多卖家选择自建独立站&#xff0c;2024年独立站占比已达35%。A…

maven的项目构建

常用构建命令 命令说明mvn clean清理编译结果&#xff08;删掉target目录&#xff09;mvn compile编译核心代码&#xff0c;生成target目录mvn test-compile编译测试代码&#xff0c;生成target目录mvn test执行测试方法mvn package打包&#xff0c;生成jar或war文件mvn insta…

定时任务和分布式任务框架

文章目录 一 Spring Task1.@Scheduled注解介绍2 基本用法(1)使用@EnableScheduling修饰启动类(2)创建定时任务的类(3)fixedDelay(4)fixedRate(5)cron3 执行多个任务4 设置异步执行5 @Async使用自定义线程池6 缺点二 xxl-job介绍架构图与其他任务调度平台的比较运行调…

git安装,配置SSH公钥(查看版本、安装路径,更新版本)git常用指令

目录 一、git下载安装 1、下载git 2、安装Git‌&#xff1a; 二、配置SSH公钥 三、查看安装路径、查看版本、更新版本 四、git常用指令 1、仓库初始化与管理 2、配置 3、工作区与暂存区管理 4、提交 5、分支管理 6、远程仓库管理 7、版本控制 8、其他高级操作 一…

[Web]ServletContext域(Application)

简介 Web应用的Application域的实现是通过ServletContext对象实现的。整个Web应用程序的所有资源共享这个域。生命周期与Web应用程序相同&#xff0c;即当前Web应用程序启动时&#xff08;以服务器视角而非访客视角&#xff09;出生&#xff0c;Web应用服务程序关闭时停止。 通…

qt c++ 进程和线程

在Qt C开发中&#xff0c;进程&#xff08;Process&#xff09;和线程&#xff08;Thread&#xff09;是两种不同的并发模型&#xff0c;各有适用场景和实现方式。以下是详细对比和实际开发中的用法总结&#xff1a; 一、进程&#xff08;Process&#xff09; 进程是操作系统资…

【鸿蒙开发】OpenHarmony调测工具hdc使用教程(设备开发者)

00. 目录 文章目录 00. 目录01. OpenHarmony概述02. hdc简介03. hdc获取04. option相关的命令05. 查询设备列表的命令06. 服务进程相关命令07. 网络相关的命令08. 文件相关的命令09. 应用相关的命令10. 调试相关的命令11. 常见问题12. 附录 01. OpenHarmony概述 OpenHarmony是…

手写简易Tomcat核心实现:深入理解Servlet容器原理

目录 一、Tomcat概况 1. tomcat全局图 2.项目结构概览 二、实现步骤详解 2.1 基础工具包&#xff08;com.qcby.util&#xff09; 2.1.1 ResponseUtil&#xff1a;HTTP响应生成工具 2.1.2 SearchClassUtil&#xff1a;类扫描工具 2.1.3 WebServlet&#xff1a;自定义注解…

【Java开发指南 | 第三十四篇】IDEA没有Java Enterprise——解决方法

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 1、新建Java项目2、单击项目名&#xff0c;并连续按两次shift键3、在搜索栏搜索"添加框架支持"4、勾选Web应用程序5、最终界面6、添加Tomcat 1、新建Java项目 2、单击项目名&#xff0c;并连续按两次…

在MATLAB中实现PID控制仿真

在MATLAB中实现PID控制仿真可以通过代码编程或Simulink图形化建模两种方式完成。以下是两种方法的详细操作步骤和示例&#xff1a; 方法1&#xff1a;使用MATLAB脚本编程&#xff08;基于控制系统工具箱&#xff09; 步骤1&#xff1a;定义被控对象的数学模型 假设被控对象是…

Conda常用命令汇总

Conda 是一个流行的包管理器和环境管理工具&#xff0c;广泛应用于数据科学、机器学习等领域。它可以帮助我们管理 Python 包以及不同版本的环境&#xff0c;避免包冲突&#xff0c;提升项目的可复现性。以下是一些常用的 Conda 命令&#xff0c;涵盖环境创建、管理、包安装等常…

大数据实时分析:ClickHouse、Doris、TiDB 对比分析

1. 引言 在大数据分析领域,实时分析需求越来越重要。ClickHouse、Doris 和 TiDB 作为当前流行的实时分析数据库,各自针对不同的应用场景和数据特性进行了优化。本文将对比它们的核心架构、适用场景以及查询优化方法,帮助数据开发人员选择合适的工具。 2. 核心架构对比 2.…

蓝桥杯历年真题题解

1.轨道炮&#xff08;数学模拟&#xff09; #include <iostream> #include <map> using namespace std; const int N1010; int x[N],y[N],v[N]; char d[N]; int main() {int n;int ans-100;cin>>n;for(int i1;i<n;i)cin>>x[i]>>y[i]>>v…

Pytorch的一小步,昇腾芯片的一大步

Pytorch的一小步&#xff0c;昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息&#xff1a;PyTorch最新2.1版本宣布支持华为昇腾芯片&#xff01; 1、 发生了什么事儿&#xff1f; 在2023年10月4日PyTorch 2.1版本的发布博客上&#xff0c;PyTorch介绍的beta版本…

嵌入式硬件篇---手柄控制控制麦克纳姆轮子

文章目录 前言1. 变量定义2. 摇杆死区设置3. 模式检查4. 摇杆数据处理4.1 右摇杆垂直值&#xff08;psx_buf[7]&#xff09;4.2 右摇杆水平值&#xff08;psx_buf[8]&#xff09;4.3 左摇杆水平值&#xff08;psx_buf[5]&#xff09;4.4 左摇杆垂直值&#xff08;psx_buf[6]&am…

阿里千问大模型(Qwen2.5-VL-7B-Instruct)部署

参考链接 知乎帖子 B站视频 huggingface 镜像网站&#xff08;不太全&#xff0c;比如 Qwen/Qwen2.5-VL-7B-Instruct就没有&#xff09; huggingface 5种下载方式汇总 通过huggingface-cli下载模型 不一样的部分是预训练权重的下载和demo 首先安装huggingface_hub pip insta…

Jenkins在Windows上的使用(二):自动拉取、打包、部署

&#xff08;一&#xff09;Jenkins全局配置 访问部署好的Jenkins服务器网址localhost:8080&#xff0c;完成默认插件的安装后&#xff0c;接下来将使用SSH登录远程主机以实现自动化部署。 1. 配置插件 选择dashboard->Manage Jenkins->plugins 安装下面两个插件  …