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

news2025/7/22 6:59:33

前言

为什么说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: 8081

spring:
  application:
  name: spring-ai-deepseek-chat-model-example
  ai:
    deepseek: ## 这一行是你选择的LLM模型,如果是openai,这里就填openai, base-url就是填对应厂商的地址
      api-key: ${你申请的apikey}
      base-url: "https://api.deepseek.com"
      chat:
        options:
          model: deepseek-chat
      embedding:
        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.coloradmin.cn/o/2398636.html

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

相关文章

快速上手pytest

1. pytest的基础 1.1 什么是pytest pytest 是 python 中的一个测试框架&#xff0c;用于编写简洁、可扩展的测试代码&#xff0c;帮助开发者验证结果是否与预期相符。 python 中有很多的测试框架&#xff0c;那我们为什么要学习 pytest 呢&#xff1f; pytest 的优势&…

设备驱动与文件系统:02 键盘

操作系统中键盘驱动的讲解 在这一讲中&#xff0c;我将为大家讲解键盘相关内容。从上一讲开始&#xff0c;我们进入了操作系统第四个部分的学习&#xff0c;也就是操作系统对设备的驱动与管理。 上一讲我们探讨的是显示器&#xff0c;并且提到&#xff0c;一个终端设备是由显示…

交通违法拍照数据集,可识别接打电话,不系安全带的行为,支持YOLO,COCO JSON,VOC XML格式的标注数据集 最高正确识别率可达88.6%

交通违法拍照数据集 数据集概述 数据来源&#xff1a;交通监控摄像头、执法记录仪、公开数据集数据类型&#xff1a;图像、视频、元数据&#xff08;时间、地点、车辆信息&#xff09;违法类型标注&#xff1a;接打电话、未系安全带 数据采集与标注方法 采集设备&#xff1…

Qt OpenGL 3D 编程入门

Qt 提供了强大的 OpenGL 集成功能&#xff0c;使得在 Qt 应用中实现 3D 图形变得更加简单。以下是使用 Qt 进行 OpenGL 3D 编程的基础知识。 1. 环境配置 创建 Qt 项目 新建 Qt Widgets Application 项目 在 .pro 文件中添加 OpenGL 模块&#xff1a; qmake QT co…

性能优化 - 工具篇:基准测试 JMH

文章目录 Pre引言1. JMH 简介2. JMH 执行流程详解3. 关键注解详解3.1 Warmup3.2 Measurement3.3 BenchmarkMode3.4 OutputTimeUnit3.5 Fork3.6 Threads3.7 Group 与 GroupThreads3.8 State3.9 Setup 与 TearDown3.10 Param3.11 CompilerControl 4. 示例代码与分析4.1 关键点解读…

Nginx网站服务:从入门到LNMP架构实战

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年5月30日14点22分 前言 说起Web服务器&#xff0c…

Java面试八股--08-数据结构和算法篇

1、怎么理解时间复杂度和空间复杂度 时间复杂度和空间复杂度一般是针对算法而言&#xff0c;是衡量一个算法是否高效的重要标准。先纠正一个误区&#xff0c;时间复杂度并不是算法执行的时间&#xff0c;在纠正一个误区&#xff0c;算法不单单指冒泡排序之类的&#xff0c;一个…

Java面试八股--06-Linux篇

目录 一、Git 1、工作中git开发使用流程&#xff08;命令版本描述&#xff09; 2.Reset与Rebase&#xff0c;Pull与Fetch的区别 3、git merge和git rebase的区别 4、git如何解决代码冲突 5、项目开发时git分支情况 二、Linux 1、Linux常用的命令 2、如何查看测试项目的…

dvwa7——SQL Injection

LOW&#xff1a; f12打开hackbar 一&#xff1a;判断注入类型 输入id1报错 闭合单引号 &#xff0c;页面恢复正常 所以为单引号字符型 二&#xff1a;开始攻击 1.判断列数 ?id1 order by 2-- 到3的时候开始报错&#xff0c;所以一共两列 2.爆回显位置 ?id-1 union s…

sqlite3 命令行工具详细介绍

一、启动与退出 启动数据库连接 sqlite3 [database_file] # 打开/创建数据库文件&#xff08;如 test.db&#xff09; sqlite3 # 启动临时内存数据库 (:memory:) sqlite3 :memory: # 显式启动内存数据库文件不存在时自动创建不指定文件名则使用临时内…

ubuntu 22.04 编译安装nignx 报错 openssl 问题

前言 Ubuntu 20.04 中安装 Nginx (通过传包编译的方式)、开启关闭防火墙、开放端口号 在ubuntu 22.04.3 服务器上照着上面的文章 通过传包编译的方式安装nginx-1.18.0 的时候报错&#xff0c;报错内容如下&#xff1a; src/event/ngx_event_openssl.c: In function ‘ngx_ssl…

线程相关面试题

提示&#xff1a;线程相关面试题&#xff0c;持续更新中 文章目录 一、Java线程池1、Java线程池有哪些核心参数&#xff0c;分别有什么的作用&#xff1f;2、线程池有哪些拒绝策略&#xff1f;3、说一说线程池的执行流程?4、线程池核心线程数怎么设置呢&#xff1f;4、Java线程…

pikachu通关教程-目录遍历漏洞(../../)

目录遍历漏洞也可以叫做信息泄露漏洞、非授权文件包含漏洞等. 原理:目录遍历漏洞的原理比较简单&#xff0c;就是程序在实现上没有充分过滤用户输入的../之类的目录跳转符&#xff0c;导致恶意用户可以通过提交目录跳转来遍历服务器上的任意文件。 这里的目录跳转符可以是../…

Maven-生命周期

目录 1.项目对象模型 2.依赖管理模型 3.仓库&#xff1a;用于存储资源&#xff0c;管理各种jar包 4.本地仓库路径 1.项目对象模型 2.依赖管理模型 3.仓库&#xff1a;用于存储资源&#xff0c;管理各种jar包 4.本地仓库路径

Matlab实现LSTM-SVM回归预测,作者:机器学习之心

Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心 目录 Matlab实现LSTM-SVM回归预测&#xff0c;作者&#xff1a;机器学习之心效果一览基本介绍程序设计参考资料 效果一览 基本介绍 代码主要功能 该代码实现了一个LSTM-SVM回归预测模型&#xff0c;核心流…

Spring Boot 自动配置原理:从入门到精通

Spring Boot 的自动配置是其核心特性之一&#xff0c;它极大地简化了 Spring 应用的开发&#xff0c;让开发者可以专注于业务逻辑&#xff0c;而无需编写大量的配置代码。 本文将深入探讨 Spring Boot 自动配置的原理&#xff0c;帮助你理解其工作机制&#xff0c;并能灵活运用…

腾讯 ovCompose 开源,Kuikly 鸿蒙和 Compose DSL 开源,腾讯的“双”鸿蒙方案发布

近日&#xff0c;腾讯的 ovCompose 和 Kuikly 都发布了全新开源更新&#xff0c;其中 Kuikly 在之前我们聊过&#xff0c;本次 Kuikly 主要是正式开源鸿蒙支持部分和 Compose DSL 的相关支持&#xff0c;而 ovCompose 是腾讯视频团队基于 Compose Multiplatform 生态推出的跨平…

PYTHON调用讯飞C/C++动态库实现离线语音合成并且实时播放

语音合成(Text-to-Speech, TTS)技术在现代应用中扮演着越来越重要的角色&#xff0c;从智能客服到有声读物&#xff0c;从导航系统到辅助工具&#xff0c;TTS技术无处不在。本文将详细介绍如何使用Python结合科大讯飞的离线SDK实现一个本地化的语音合成系统。 技术背景 离线语…

黑马Java面试笔记之 消息中间件篇(RabbitMQ)

一. 消息丢失问题 RabbitMQ如何保证消息不丢失&#xff1f; 使用场景有&#xff1a; 异步发送&#xff08;验证码、短信、邮件... &#xff09;MYSQL和Redis&#xff0c;ES之间的数据同步分布式事务削峰填谷...... 消息丢失原因会有三种情况&#xff0c;分别分析一下 1.1 生…

Redisson学习专栏(五):源码阅读及Redisson的Netty通信层设计

文章目录 前言一、分布式锁核心实现&#xff1a;RedissonLock源码深度解析1.1 加锁机制&#xff1a;原子性与重入性实现1.2 看门狗机制&#xff1a;锁自动续期设计1.3 解锁机制&#xff1a;安全释放与通知1.4 锁竞争处理&#xff1a;等待队列与公平性1.5 容错机制&#xff1a;异…