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

Spring Ai 从Demo到搭建套壳项目(一)初识与实现与deepseek对话模式

前言

为什么说Java长青,主要是因为其生态圈完善,Spring又做了一款脚手架,把对接各个LLM厂商的sdk做了一遍,形成一系列的spring-ai-starter-** 的依赖。 目前为止版本去到1.0.0.M6,golang跟不上了吧, Make Java Greate Again!!

我打算这个系列介绍这个spring-ai-starter和各个LLM的关系,介绍实际操作,演示一下官网的一些关键点和没讲到的细节,还有后续会讲如何使用spring-ai搭建一个套壳项目(啥是套壳项目下一章会讲),从后端,到spring-ai对接,到前端的制作。比较希望大家已经对LLM有些基础的理解。

一、技术框架

如果没有框架,你需要做什么?

  1. 你要自己写http调用代码,来分别对各个LLM模型接口(或者SDK,例如https://api-docs.deepseek.com/zh-cn/api/create-chat-completion/) 的请求,等待他结果的返回,解析响应。spring-ai就同一个了接口。
  2. 还有支持Advisor,就像面向切面那样,发送请求前,检查文本有没有命中禁用词,就例如企业不允许把代码透露出去,也不允许使用某些黑词,就可以这里检查。
  3. 还有支持MCP调用能力,如果不对接spring-ai,你就要自己实现MCP协议的调用代码,来达到调用别的服务。例如:后续会实现的使用高德地图mcp,得到高德查看坐标工具,交通工具,路线规划工具,天气工具。
  4. 支持会话跟踪,如果你不接spring-ai,你还需要自己记录会话到表,或者让前端把说过的话,一次过传给后端,后端再告诉ai来做context上下文跟踪。
  5. RAG检索增强,可以通过他告诉ai又额外的一套文本,让某个LLM分析这个文本,得到你想要的答案。我觉得这个点可以用于客服话术,先拟定好话术,通过RAG解析话术的文本,当用户跟ai对话的时候,附带这个解析后的spring-ai的Document类对象,得到话术的结果。例如:设定话术用户发送一串数字,就回复“这个订单有什么问题?”

那目前市面上有什么框架呢?

在这里插入图片描述

  1. 目前看到的java相关的有org.springframework.ai这个group下的
spring-ai-starter-**

这个前缀的依赖。其后缀包括open-ai, aliyun , deepseek, anthropic等,他就是整合了对多个LLM厂商的接口,统一封装,底层还是调用各个LLM厂商的SDK。

那为什么spring要封装呢?其实你看名字叫starter就知道了,一般叫starter的都是脚手架,就如springcloud,springboot那样,通过yml或者properties的配置,来实现自动装配,生成一个springbean,
方便你去调用。

spring:ai:openai:api-key: ${你的key}base-url: ${请求openai的地址}deepseek:api-key: ${你的key}base-url: "https://api.deepseek.com"chat:options:model: deepseek-chat

如这里就固定了层级格式,让你填写地址和key就可以了。

  1. 还有alibaba提供的框架,他基于上面这个依赖做的封装,这种就是套壳

大家有没有发现上面代码需要对每个大预言模型都生成分别的api-key,所以就有人就想自己做一个统一的使用各个LLM地方,就如Cursor、Pandora,你看这些软件上,可以访问各个LLM的模型而不用对各个模型分别付费,这种统一地方的软件就是给钱包月或者按次数买1个apikey,就可以用各个LLM模型了

所以spring-ai-alibaba-stater-**系列,也是要去阿里百炼(旧名灵积)上生成一个key,就可以去使用不同的模型的一款套壳框架(https://bailian.console.aliyun.com/), 现在也是免费的,但他可以给你免费使用这么多个LLM也是有成本的,以后还是得收费。

二、现在就演示一下,如何对接spring-ai,并使用deepseek模型进行对话

当前先了解spring-ai这个基础框架,第三章再来演示如何对接spring-ai-alibaba版的。因为spring-ai-alibaba现在免费,你当前可以基于这个套壳框架,再套壳后,给商用起来,但是当alibaba开始收费,你又要对接各个厂商了,而且某些公司还不能用alibaba的api-key,所以spring-ai这个基础框架还是要了解的。

建立maven 工程

引入依赖,一定要使用jdk 17 ,因为springboot已经3了

<properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.3.4</version></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-deepseek</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId> <version>3.3.4</version></dependency></dependencies>

spring-boot-starter-webflux这个东西就是响应式接口的关键,没有他,就没有持续输出文字的效果 spring-ai-starter-model-deepseek 这个就是spring对deepseek的封装。

配置application.xml

server:port: 8081spring:application:name: spring-ai-deepseek-chat-model-exampleai:deepseek: ## 这一行是你选择的LLM模型,如果是openai,这里就填openai, base-url就是填对应厂商的地址api-key: ${你申请的apikey}base-url: "https://api.deepseek.com"chat:options:model: deepseek-chatembedding:enabled: false

创建主类

@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class,args);}
}

创建Controller

@RequestMapping("/openai")
@ResponseBody
@Controller
public class DeepSeekChatModelController {private final ChatModel deepSeekChatModel;// 主要就是这个地方,springboot已经把yml里的配置,生成好一个叫ChatModel的bean,注入进来controller里就可以直接使用了public DeepSeekChatModelController(ChatModel chatModel) {this.deepSeekChatModel = chatModel;}// 这个是同步等待LLM的结果,再回复给前端。@GetMapping("/simple/chat/{prompt}")public String simpleChat (@PathVariable(value = "prompt") String prompt) {return deepSeekChatModel.call(new Prompt(prompt)).getResult().getOutput().getText();}/*** Stream 流式调用。可以使大模型的输出信息实现打字机效果。* 这个就是sse方式回复内容给前端,就不用等所有的内容都收到才给前端* @return Flux<String> types.*/@GetMapping("/stream/chat/{prompt}")public Flux<String> streamChat (@PathVariable(value = "prompt") String prompt,HttpServletResponse response) {response.setCharacterEncoding("UTF-8");Flux<ChatResponse> stream = deepSeekChatModel.stream(new Prompt(prompt));return stream.map(resp -> resp.getResult().getOutput().getText());}
}

实验结果

通过请求与deepseek对话,用localhost:8081/openai/simple/chat/或者localhost:8081/openai/stream/chat/ 两个接口都是可以的。
在这里插入图片描述

三、 但是大家有没有发现,拿不到实时数据,而是只教你怎么去拿实时数据

因为deepseek只是一个文本类搜索和推荐的工具,他的数据是一年以前的搜索库里的数据,不是最新的。
那么要如何获取最新的数据呢?请看下一章。

公————地藏思维

http://www.xdnf.cn/news/756577.html

相关文章:

  • MATLAB实战:Arduino硬件交互项目方案
  • 【Go-补充】Sync包
  • QtWidgets,QtCore,QtGui
  • uniapp uni-id 如果是正式项目,需自行实现发送邮件的相关功能
  • RAGflow详解及实战指南
  • 深度学习中常见的超参数对系统的影响
  • Vue 3 组件化设计实践:构建可扩展、高内聚的前端体系
  • 初学大模型部署以及案例应用(windows+wsl+dify+mysql+Ollama+Xinference)
  • 「数据采集与网络爬虫(使用Python工具)」【数据分析全栈攻略:爬虫+处理+可视化+报告】
  • (javaSE)Java数组进阶:数组初始化 数组访问 数组中的jvm 空指针异常
  • 卷积神经网络(CNN)完全指南:从原理到实战
  • Java 中 MySQL 索引深度解析:面试核心知识点与实战
  • 牛顿迭代算法-深度解析
  • USART 串口通信全解析:原理、结构与代码实战
  • YOLOv11改进 | Conv/卷积篇 | 全维度动态卷积ODConv与二次创新C3k2助力YOLOv11有效涨点
  • GIS数据类型综合解析
  • 【笔记】在 MSYS2(MINGW64)中安装 Python 工具链的记录
  • 【计网】第六章(网络层)习题测试集
  • 【科研绘图系列】R语言绘制论文组合图形(multiple plots)
  • 某数字藏品qm加密算法技术解析:多层混合加密体系的深度剖析
  • RV1126-OPENCV 图像叠加
  • 【PhysUnits】15.8 引入P1后的减法运算(sub.rs)
  • 图文详解Java集合面试题
  • TDengine 基于 TDgpt 的 AI 应用实战
  • 【论文阅读 | PR 2024 |ICAFusion:迭代交叉注意力引导的多光谱目标检测特征融合】
  • vue3中的ref和reactive
  • pc端小卡片功能-原生JavaScript金融信息与节日日历
  • 2024 CKA模拟系统制作 | Step-By-Step | 16、题目搭建-sidecar 代理容器日志
  • 工作流引擎-06-流程引擎(Process Engine)对比 Flowable、Activiti 与 Camunda 全维度对比分析
  • 一位汽车行业从业人员对Simulink热度变化的观察与讨论 (2024)