当前位置: 首页 > news >正文

SpringAI+DeepSeek大模型应用开发

目录

大模型应用开发

模型部署

模型部署方案对比

模型部署-云部署

模型部署-本地部署

调用大模型

AI应用开发技术架构

SpringAI

对话机器人-快速入门

对话机器人-会话日志

对话机器人-会话记忆

一、定义会话存储方式

二、配置会话记忆Advisor

三、添加会话id

对话机器人-会话历史记录功能

大模型应用开发

模型部署

模型部署方案对比

云部署

优点:

  • 前期成本低
  • 部署维护简单
  • 弹性扩展
  • 全球访问

缺点:

  • 数据隐私性不高
  • 网络依赖性强
  • 长期成本高

本地部署

优点:

  • 数据安全
  • 不依赖外部部署
  • 长期成本低
  • 高度定制

缺点:

  • 初始成本高
  • 维护复杂
  • 部署周期长

开放API

优点:

  • 前期成本极低
  • 无需部署
  • 无需维护
  • 全球访问

缺点:

  • 数据隐私性不高
  • 网络依赖性强
  • 定制限制

小型企业开发以及个人学习应用开发可以使用开放API,如果要长期使用的话,用云部署或本地部署较好。

模型部署-云部署

云平台公司地址
阿里百炼阿里巴巴https://bailian.console.aliyun.com
腾讯TI平台腾讯https://cloud.tencent.com/product/ti
千帆平台百度https://console.bce.baidu.com/gianfan/overview
SiliconCloud硅基流动https://siliconflow.cn/zh-cn/siliconcloud
火山方舟-火山引擎字节跳动https://www.volcengine.com/product/ark

模型部署-本地部署

本地部署最简单的一种方案就是使用ollama,官网地址:https://ollama.com

打开ollama的官网可以选择系统下载

左上角Models里面会有各个AI大模型

点击你要选择的大模型,下面会有许多版本让你选择,后面的1.5b,7b指的是它的算力,数值越大对电脑配置要求越高,数值最大的就是我们说的满血版,其余都是阉割版,右上角是对应使用的命令,打开命令提示符并输入指令它就会自动为你下载。

调用大模型

下面是DeepSeek官方给出的一段API示例代码:

AI应用开发技术架构

SpringAI

对话机器人-快速入门

1.引入依赖(可以在创建项目时在加入依赖时AI下边勾选对应依赖)

    <properties><java.version>17</java.version><spring-ai.version>1.0.3</spring-ai.version></properties><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></dependency><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

2.配置大模型

spring:application:name: demoai:ollama:base-url: http://localhost:11434chat:model: deepseek-r1:8b

3.配置客户端

package com.example.config;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class CommonConfiguration {@Beanpublic ChatClient chatClient(OllamaChatModel model) {return ChatClient.builder(model).build();}
}

都配置好以后就能书写请求然后启动项目发送请求了

@RequiredArgsConstructor
@RestController
@RequestMapping("/ai")
public class ChatController {private final ChatClient chatClient;@RequestMapping("/chat1")
//    阻塞式返回(全部输出完才返回)public String chat(String prompt) {return chatClient.prompt().user(prompt).call().content();}//    流式返回(输出过程中返回)//这里要在返回值加上 produces = "text/html;charset=utf-8",否则会乱码@RequestMapping(value = "/chat2", produces = "text/html;charset=utf-8")public Flux<String> stream(String prompt) {return chatClient.prompt().user(prompt).stream().content();}
}

对话机器人-会话日志

SpringAI利用AOP原理提供了AI会话时的拦截、增强等功能,也就是Advisor。

SpringAI在提示词发送到AI大模型之前(②Before advising)和大模型结果产生后但是发送到用户之前(⑤After advising)进行了环绕增强,我们可以在②位置处记录提示词(作为记忆功能),在⑤处记录输出的内容(记录返回日志)。

SpringAI为我们提供了Advisor的实现,可以直接使用不需要我们自己去写。

配置日志选项并且设置日志级别为DEBUG

@Configuration
public class CommonConfiguration {@Beanpublic ChatClient chatClient(OllamaChatModel model) { //创建ChatClient工厂实例return ChatClient.builder(model).defaultSystem("你是皮卡丘,请以皮卡丘的视角回答").defaultAdvisors(new SimpleLoggerAdvisor()) //配置日志Advisor.build(); //创建ChatClient实例}
}
#配置日志级别为debug
logging:level:org.springframework.ai.chat.client: DEBUGcom.example.demo: DEBUG

对话机器人-会话记忆

大模型是不具备记忆能力的,要想让大模型记住之前聊天的内容,唯一的办法就是把之前聊天的内容与新的提示词一起发给大模型。

一、定义会话存储方式

要定义会话存储方式,可以去实现ChatMemory接口,然后重写对应方法去实现。

SpringAI也提供了一个默认的实现InMemoryChatMemory(最新1.0.3版本已经换成MessageWindowChatMemory了),但这个是存储在内存中的,服务器重启记忆就没了。

二、配置会话记忆Advisor

三、添加会话id

上面advisors里的AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY在最新的1.0.3中已经修改为ChatMemory.CONVERSATION_ID

最后综合代码如下:

@Configuration
public class CommonConfiguration {@Beanpublic ChatMemory chatMemory() {// 创建Memory实例return MessageWindowChatMemory.builder().build();}@Beanpublic ChatClient chatClient(OllamaChatModel model, ChatMemory chatMemory) { //创建ChatClient工厂实例return ChatClient.builder(model).defaultSystem("你是皮卡丘,请以皮卡丘的视角回答").defaultAdvisors(new SimpleLoggerAdvisor(),// 配置MemoryAdvisorMessageChatMemoryAdvisor.builder(chatMemory).build()) //配置日志Advisor.build(); //创建ChatClient实例}
}
//    流式返回(输出过程中返回)//这里要在返回值加上 produces = "text/html;charset=utf-8",否则会乱码@RequestMapping(value = "/chat2", produces = "text/html;charset=utf-8")//再传入一个chatIdpublic Flux<String> stream(String prompt, String chatId) {return chatClient.prompt().user(prompt)//这里的key值是一个固定的参数,不能随便修改.advisors(a -> a.param(CONVERSATION_ID, chatId) ).stream().content();}
}

对话机器人-会话历史记录功能

第一个请求是要查询到对应AI会话业务下的所有会话ID,即上图中左侧列表中的两个就是该请求的返回值。 第二个请求是要根据会话类型和会话id返回用户和AI的对话记录。

我们先要写记录会话ID接口,然后再写查询会话id记录,最后根据会话id查询出具体的会话内容。

先写出记录会话记录和查询会话id记录的方法

public interface ChatHistoryRepository {// 保存会话记录void save(String type, String chatId);// 获取会话ID记录List<String> get(String type);
}
public class InMemoryChatHistoryRepository implements ChatHistoryRepository{private final Map<String, List<String>> chatHistory = new HashMap<>();// 保存会话记录@Overridepublic void save(String type, String chatId) {//先判断该类型会话是否已经存在会话id列表,如果不存在则创建一个空列表if (!chatHistory.containsKey(type)){chatHistory.put(type, List.of());}//从缓存中获取该类型会话的会话id列表List<String> chatHistoryList = chatHistory.get(type);//如果该类型列表中已经存在该会话id,则直接返回if (chatHistoryList.contains(chatId)){return;}//否则将新的会话id添加到该类型列表中chatHistoryList.add(chatId);}//    根据会话类型获取会话ID记录@Overridepublic List<String> get(String type) {List<String> chatHistoryList = chatHistory.get(type);//如果该类型列表不存在,则返回一个空列表return chatHistoryList != null ? chatHistoryList : List.of();}
}

在对话的时候对会话记录进行保存

我们创建实例时用的是spring ai提供的方法,我们对话的具体内容也由它进行存储记录,要查询到会话内容就要看它内部是如何查询的。

Ctrl+左键进去我们可以看到下面的方法,它需要会话id返回Message类型的集合。

进入到Message里面,我们需要看它返回的是否是我们需要的格式,Message是一个接口,里面有一个方法 getMessageType() 并且其继承了Content。

进入到 getMessageType() 方法里,其返回的是对话的角色(类型),我们只需要其中的 user(用户提问)和 assistant(ai回答)。

进入到Content中,里面的getText()方法就是获取对话具体内容的方法。

看完了spring ai提供的方法和返回格式,我们能知道其提供的格式不是我们想要的,因此我们就需要写一个VO类来编写我们需要的返回格式。

@Data
@NoArgsConstructor
public class MessageVO {private String role;private String content;// 构造函数public MessageVO(Message message) {//我们从message中获取role和contentswitch (message.getMessageType()){//保留下来我们需要的角色case USER -> this.role = "user";case ASSISTANT -> this.role = "assistant";default -> this.role = "";}this.content = message.getText();}
}

最后我们把获取会话记录的方法写出来就完成了。

    @GetMapping("/{type}/{chatId}")public List<MessageVO>  getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId) {//获取会话记录List<Message> messages = chatMemory.get(chatId);if (messages == null){return List.of();}return messages.stream().map(MessageVO::new).toList();}

http://www.dtcms.com/a/499503.html

相关文章:

  • 递归-24.两两交换链表中的节点-力扣(LeetCode)
  • 【Java零基础·第12章】Lambda与Stream API
  • Qemu-NUC980(八):GPIO Controller
  • 外贸型企业网站建设开源商城源码
  • JS逆向-安全辅助项目Yakit热加载魔术方法模版插件语法JSRpc进阶调用接口联动
  • 使用IOT-Tree接入各种数据转BACnet模拟设备输出
  • 网站搭建说明北京海淀区是几环
  • 基于多模态AI技术的传统行业智能化升级路径研究——以开源AI大模型、AI智能名片与S2B2C商城小程序为例
  • 【C语言进阶】指针进阶_数组指针的使用,数组参数和指针参数
  • PySide6 控件插入日期时间(QDateTime)
  • 网站建设 jsp php垂直网站建设
  • 招商网站大全企业官方网站建设的流程
  • 征程 6 | 工具链如何支持 Matmul/Conv 双 int16 输入量化?
  • 【案例实战】鸿蒙分布式调度:跨设备协同实战
  • 中英文网站设计网站开发投标文件
  • Langgraph译文1:让AI自主决策的代理架构
  • 如何让百度能查到自己衡阳专业的关键词优化终报价
  • 为什么.NET的System.IO.Compression无法解压zlib流
  • 微信小程序:日常零售供应系统
  • 安卓如何查看settings是被哪个进程更新的?相关dumpsys命令剖析
  • 网络营销方式案例分析郑州网站优化推广
  • 下载软件太慢的加速操作
  • 网站改版技术要求git wordpress中文免费主题
  • 从应力到位移:混合模式分层损伤起始点推导
  • Gartner 2025年新兴技术成熟度曲线
  • HCIA DAY2
  • 【Go】--文件上传
  • 基于SpringBoot及PostgreSQL的国家减肥食谱管理项目(中):食谱与菜单配置搭建
  • 网站建设 需要准备材料安徽六安特产有哪些
  • Qt的QT_QPA_EGLFS_INTEGRATION环境变量浅解