Spring AI 1.0.1 使用教程

项目简介

作为一个Java的开发者  听到Java也有ai框架了  很高兴~~~

本来想学一下SpringAI但是网上卖课的一大堆,并且大部分课程都是五月的,到2025年的8月份,SpringAI的版本做了很多更新,所以我本人参考网上示例,很多代码走不通,一些方法被废弃了,搞得有点破防。。。

于是我自行阅读了SpringAI1.0.1的官方教程  

目前应该是全网最新的示例教程 ,欢迎初学者小白git clone  

前人栽树 后人乘凉   给大家避坑的   可以点赞收藏加个绿泡泡不??

作者邮箱:shibaizhelianmeng@163.com  绿泡泡wx@:EonNetWork 

代码仓库:

代码拉取下来就可以跑

github:

Lappercn/SpringAI-examplehttps://github.com/Lappercn/SpringAI-examplegitee:

SpringAI1.0.1教程: 本项目是一个基于 Spring AI 1.0.1 的聊天应用示例,集成了 Ollama 模型,展示了如何使用 Spring AI 的核心功能: - 多模型动态切换 - 聊天记忆管理 - 自定义 Advisor(日志记录、拦截器等) - 用户会话隔离 - 流式响应处理https://gitee.com/Lapper/ChatAI

教程如下:

本项目是一个基于 Spring AI 1.0.1 的聊天应用示例,集成了 Ollama 模型,展示了如何使用 Spring AI 的核心功能:

  • 多模型动态切换
  • 聊天记忆管理
  • 自定义 Advisor(日志记录、拦截器等)
  • 用户会话隔离
  • 流式响应处理

环境要求

  • Java 17+
  • Spring Boot 3.5.4
  • Spring AI 1.0.1
  • Ollama(本地运行)

快速开始

1. 安装 Ollama

# 下载并安装 Ollama
curl -fsSL https://ollama.ai/install.sh | sh# 拉取模型(示例)
ollama pull deepseek-r1:7b
ollama pull qwen2:7b
ollama pull llama3.2:3b

2. 启动项目

# 克隆项目
git clone <your-repo-url>
cd ChatAI# 启动应用
./mvnw spring-boot:run

3. 测试接口

# 基本聊天
curl "http://localhost:8080/ai/chat?prompt=你好&chatid=1&model=deepseek-r1:7b"# 切换模型
curl "http://localhost:8080/ai/chat?prompt=讲个笑话&chatid=1&model=qwen2:7b"

核心功能详解

1. ChatClient 配置

文件位置: src/main/java/com/example/chatai/Config/CommonConfigOllama.java

@Configuration
public class CommonConfigOllama {@Beanpublic ChatMemory chatMemory(){return MessageWindowChatMemory.builder().build();}@Beanpublic ChatClient client(OllamaChatModel model){return ChatClient.builder(model).defaultSystem("你是一个可爱的小女孩你的回答语气 非常可爱是一个智能助手").defaultAdvisors(new SimpleLoggerAdvisor(),MessageChatMemoryAdvisor.builder(chatMemory()).build(),new CustomLoggingAdvisor()).build();}
}

核心接口说明:

  • ChatClient.builder(model): 创建聊天客户端构建器
  • .defaultSystem(String): 设置默认系统提示词
  • .defaultAdvisors(...): 注册默认的 Advisor 链

2. 动态模型切换

文件位置: src/main/java/com/example/chatai/Controller/ChatController.java

@GetMapping(value = "/chat", produces = "text/html;charset=utf-8")
public Flux<String> chat(String prompt, int chatid, @RequestParam(defaultValue = "deepseek-r1:7b") String model) {return client.prompt().options(OllamaOptions.builder().model(model).build()).user(prompt).advisors(a -> a.param(CONVERSATION_ID, chatid)).stream().content();
}

接口定义:

  • client.prompt(): 开始构建提示
  • .options(OllamaOptions): 设置模型参数
  • .user(String): 设置用户消息
  • .advisors(...): 配置会话级 Advisor
  • .stream(): 启用流式响应
  • .content(): 获取内容流

OllamaOptions 常用配置:

OllamaOptions.builder().model("deepseek-r1:7b")           // 模型名称.temperature(0.7f)                 // 温度参数.topP(0.9f)                       // Top-P 采样.maxTokens(1000)                  // 最大 Token 数.build()

3. 聊天记忆管理

3.1 基础记忆配置
@Bean
public ChatMemory chatMemory(){// 滑动窗口记忆(保留最近 N 条消息)return MessageWindowChatMemory.builder().maxMessages(10)           // 最大消息数.build();
}
3.2 用户会话隔离

通过 CONVERSATION_ID 实现多用户隔离:

.advisors(a -> a.param(CONVERSATION_ID, chatid))

不同用户示例:

# 用户1的对话
curl "http://localhost:8080/ai/chat?prompt=我叫张三&chatid=1"
curl "http://localhost:8080/ai/chat?prompt=我叫什么名字?&chatid=1"# 用户2的对话
curl "http://localhost:8080/ai/chat?prompt=我叫李四&chatid=2"
curl "http://localhost:8080/ai/chat?prompt=我叫什么名字?&chatid=2"
3.3 持久化记忆(扩展)

自定义持久化记忆实现:

@Component
public class DatabaseChatMemory implements ChatMemory {@Autowiredprivate ChatMessageRepository repository;@Overridepublic void add(String conversationId, List<Message> messages) {// 保存到数据库messages.forEach(msg -> {ChatMessageEntity entity = new ChatMessageEntity();entity.setConversationId(conversationId);entity.setContent(msg.getContent());entity.setRole(msg.getMessageType().getValue());entity.setTimestamp(LocalDateTime.now());repository.save(entity);});}@Overridepublic List<Message> get(String conversationId, int lastN) {// 从数据库查询return repository.findTopNByConversationIdOrderByTimestampDesc(conversationId, lastN).stream().map(this::toMessage).collect(Collectors.toList());}
}

4. 自定义 Advisor 开发

4.1 日志记录 Advisor

文件位置: src/main/java/com/example/chatai/Config/CustomLoggingAdvisor.java

@Component
public class CustomLoggingAdvisor implements CallAdvisor, StreamAdvisor, Ordered {private static final Logger logger = LoggerFactory.getLogger(CustomLoggingAdvisor.class);@Overridepublic ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {// 请求前处理logger.info("请求开始: {}", request.userText());long startTime = System.currentTimeMillis();// 调用下一个节点ChatClientResponse response = chain.nextCall(request);// 响应后处理long duration = System.currentTimeMillis() - startTime;logger.info("请求完成: 耗时{}ms, 响应长度: {}", duration, response.getResult().getOutput().getContent().length());return response;}@Overridepublic Flux<ChatClientResponse> adviseStream(ChatClientRequest request, StreamAdvisorChain chain) {logger.info("流式请求开始: {}", request.userText());return chain.nextStream(request).doOnNext(chunk -> logger.debug("接收到分片: {}", chunk.getResult().getOutput().getContent())).doOnComplete(() -> logger.info("流式响应完成")).doOnError(error -> logger.error("流式响应错误", error));}@Overridepublic int getOrder() {return 100; // 执行顺序,数字越小优先级越高}
}
4.2 权限验证 Advisor
@Component
public class AuthorizationAdvisor implements CallAdvisor {@Overridepublic ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {// 从请求中获取用户信息String userId = request.advisorParams().get("userId");// 验证用户权限if (!hasPermission(userId)) {throw new UnauthorizedException("用户无权限访问");}// 检查敏感词if (containsSensitiveWords(request.userText())) {throw new IllegalArgumentException("包含敏感词汇");}return chain.nextCall(request);}private boolean hasPermission(String userId) {// 实现权限检查逻辑return true;}private boolean containsSensitiveWords(String text) {// 实现敏感词检测逻辑return false;}
}
4.3 速率限制 Advisor
@Component
public class RateLimitAdvisor implements CallAdvisor {private final Map<String, RateLimiter> limiters = new ConcurrentHashMap<>();@Overridepublic ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {String userId = request.advisorParams().get("userId");// 获取或创建限流器(每分钟10次请求)RateLimiter limiter = limiters.computeIfAbsent(userId, k -> RateLimiter.create(10.0 / 60.0));if (!limiter.tryAcquire()) {throw new TooManyRequestsException("请求过于频繁,请稍后再试");}return chain.nextCall(request);}
}

5. 配置文件详解

文件位置: src/main/resources/application.yaml

spring:application:name: ChatAIai:ollama:base-url: http://localhost:11434    # Ollama 服务地址chat:model: deepseek-r1:7b             # 默认模型options:temperature: 0.2                # 创造性参数# 日志配置
logging:level:com.example.chatai.Config.CustomLoggingAdvisor: INFOorg.springframework.ai.chat.client.advisor: DEBUGorg.springframework.ai: INFOpattern:console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

6. 完整的使用示例

6.1 基础聊天示例
@RestController
public class ExampleController {@Autowiredprivate ChatClient chatClient;// 简单聊天@GetMapping("/simple-chat")public String simpleChat(@RequestParam String message) {return chatClient.prompt().user(message).call().content();}// 带系统提示的聊天@GetMapping("/system-chat")public String systemChat(@RequestParam String message) {return chatClient.prompt().system("你是一个专业的代码审查员").user(message).call().content();}// 流式聊天@GetMapping("/stream-chat")public Flux<String> streamChat(@RequestParam String message) {return chatClient.prompt().user(message).stream().content();}
}
6.2 高级功能示例
@RestController
public class AdvancedController {@Autowiredprivate ChatClient chatClient;// 多轮对话与记忆@PostMapping("/conversation")public ResponseEntity<String> conversation(@RequestBody ConversationRequest request) {String response = chatClient.prompt().user(request.getMessage()).advisors(advisor -> advisor.param(CONVERSATION_ID, request.getUserId()).param("userId", request.getUserId())).call().content();return ResponseEntity.ok(response);}// 带选项的聊天@PostMapping("/chat-with-options")public String chatWithOptions(@RequestBody ChatRequest request) {return chatClient.prompt().options(OllamaOptions.builder().model(request.getModel()).temperature(request.getTemperature()).maxTokens(request.getMaxTokens()).build()).user(request.getMessage()).call().content();}// 函数调用示例(如果模型支持)@PostMapping("/function-call")public String functionCall(@RequestParam String query) {return chatClient.prompt().user(query).functions("getCurrentWeather", "searchDatabase").call().content();}
}

最佳实践

1. 错误处理

@RestController
public class ChatController {@GetMapping("/safe-chat")public ResponseEntity<String> safeChat(@RequestParam String message) {try {String response = chatClient.prompt().user(message).call().content();return ResponseEntity.ok(response);} catch (Exception e) {logger.error("聊天请求失败", e);return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("抱歉,服务暂时不可用");}}
}

2. 性能优化

@Configuration
public class ChatClientConfig {@Bean@Primarypublic ChatClient optimizedChatClient(OllamaChatModel model) {return ChatClient.builder(model).defaultAdvisors(// 缓存 Advisornew CacheAdvisor(),// 限流 Advisornew RateLimitAdvisor(),// 日志 Advisor(低优先级)new SimpleLoggerAdvisor()).build();}
}

3. 监控指标

@Component
public class MetricsAdvisor implements CallAdvisor {private final MeterRegistry meterRegistry;private final Counter requestCounter;private final Timer responseTimer;public MetricsAdvisor(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;this.requestCounter = Counter.builder("ai.requests.total").register(meterRegistry);this.responseTimer = Timer.builder("ai.response.duration").register(meterRegistry);}@Overridepublic ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {return Timer.Sample.start(meterRegistry).stop(responseTimer, () -> {requestCounter.increment();return chain.nextCall(request);});}
}

故障排除

常见问题

  1. 模型连接失败

    • 检查 Ollama 服务是否启动:ollama list
    • 确认模型已下载:ollama pull model-name
  2. 日志不显示

    • 检查 application.yaml 中的日志级别配置
    • 确认 Advisor 已正确注册
  3. 记忆功能不生效

    • 确认 ChatMemory Bean 正确配置
    • 检查 CONVERSATION_ID 参数传递

调试技巧

# 开启详细日志
logging:level:org.springframework.ai: DEBUGorg.springframework.web: DEBUGcom.example.chatai: DEBUG

扩展开发

自定义模型适配

@Configuration
public class CustomModelConfig {@Bean@ConditionalOnProperty(name = "app.model.provider", havingValue = "custom")public ChatModel customChatModel() {// 实现自定义模型适配return new CustomChatModel();}
}

多租户支持

@Component
public class MultiTenantAdvisor implements CallAdvisor {@Overridepublic ChatClientResponse adviseCall(ChatClientRequest request, CallAdvisorChain chain) {String tenantId = request.advisorParams().get("tenantId");// 设置租户上下文TenantContext.setCurrentTenant(tenantId);try {return chain.nextCall(request);} finally {TenantContext.clear();}}
}

参考资源

  • Spring AI 官方文档
  • Ollama 官网
  • Spring Boot 文档

联系方式

  • 作者:胖虎爱java
  • 邮箱:shibaizhelianmeng@163.com
  • CSDN:胖虎爱java

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

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

相关文章

Maven架构的依赖管理和项目构建

​​​​​​什么是依赖管理对第三方依赖包的管理&#xff0c;可以连接互联网下载项目所需第三方jar包。对自己开发的模块的管理&#xff0c;可以像引用第三方依赖包一样引用自己项目的依赖包。Maven的依赖管理方式和传统方式有什么区别传统方式&#xff1a;从官网手动下载jar包…

微信小程序开发(一):使用开发者工具创建天气预报项目

Hi&#xff0c;我是前端人类学&#xff08;之前叫布兰妮甜&#xff09;&#xff01; 从今天开始&#xff0c;我将开启一个全新的微信小程序开发系列教程&#xff0c;通过实际项目带大家系统学习小程序开发。作为系列的第一篇文章&#xff0c;我们将从最基础的环境搭建开始&…

【链表 - LeetCode】24. 两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; - 迭代 首先是直接遍历的做法&#xff0c;这里注意调整指针指向的顺序。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* List…

爬虫基础学习-链接协议分析,熟悉相关函数

1、urlparse&#xff1a;&#xff08;python标准库中的一个模块&#xff0c;解析和操作url&#xff09;标准的url链接格式&#xff1a;scheme://netloc/path;params?query#fragmentscheme&#xff08;协议&#xff09; http or https netloc&#xff08;网络位置&#xff09; …

kkfileview预览Excel文件去掉左上角的跳转HTML预览、打印按钮

上篇说了使用nginx代理kkfile预览文件&#xff0c;但是又发现个新问题&#xff0c;预览其他文件时都正常&#xff0c;但是预览.xlsx格式的时候&#xff0c;在左上角会有【跳转HTML预览】【打印】两个按钮&#xff0c;如下所示&#xff1a;这篇就来说一下如何去掉。首先这个跟kk…

阿里开源新AI code工具:qoder功能介绍

下载地址&#xff1a; https://qoder.com/ 文档地址&#xff1a; https://docs.qoder.com/ 文章目录1. AI 编码发展趋势2. 真实世界软件开发的挑战3. 我们的方法3.1. 透明度3.1.1. 知识可见性3.1.2. 执行透明度3.2. 增强上下文工程3.3. 规范驱动与任务委托3.3.1. 聊天模式&…

什么是短视频矩阵系统企业立项功能源码开发,支持OEM

短视频矩阵系统企业立项功能源码开发解析在短视频行业蓬勃发展的当下&#xff0c;企业纷纷布局短视频矩阵&#xff0c;以实现多平台、多账号的协同运营。而企业立项作为短视频矩阵项目启动的关键环节&#xff0c;其高效、规范的管理直接影响项目的推进效率与成果。为此&#xf…

当GitHub宕机时,我们如何协作?

问题背景与影响 GitHub作为主流代码托管平台的依赖现状宕机对分布式团队、CI/CD流水线、紧急修复的影响案例其他类似平台&#xff08;GitLab、Bitbucket&#xff09;的潜在连带风险 本地与离线协作方案 利用Git分布式特性&#xff1a;本地仓库继续提交&#xff0c;恢复后同步搭…

【会议跟踪】Model-Based Systems Engineering (MBSE) in Practice 2025

会议主旨与议题 会议宣传链接:https://www.sei.cmu.edu/events/mbse-in-practice/ 本次会议将于2025年8月21日位美国弗吉尼亚州阿灵顿(五角大楼所在地)举行。本次会议主旨为 MBSE in Practice: Bridging the Gap Between Theory and Success(2025)。随着软件定义系统日趋…

浏览器的渲染流程:从 HTML 到屏幕显示

在我们日常使用浏览器浏览网页时&#xff0c;往往忽略了浏览器背后复杂的渲染过程。从输入 URL 到页面最终显示在屏幕上&#xff0c;浏览器需要经过一系列精心设计的步骤。 浏览器渲染的整体流程浏览器的渲染流程可以大致分为两个主要部分&#xff1a;网络 和 渲染。当用户在地…

FastMCP 客户端服务器通信示例:从入门到实战(STDIO 传输)

引言 在现代分布式系统和AI应用中&#xff0c;模型上下文协议&#xff08;MCP&#xff09;扮演着重要角色&#xff0c;它负责协调客户端与服务器之间的通信&#xff0c;尤其是在需要频繁交互的场景中。本文将介绍如何使用FastMCP库快速实现客户端与服务器之间的通信&#xff0c…

宝可梦肉鸽 PC/手机双端 多种存档 全闪光 无限金币 全宝可梦解锁 免安装中文版

网盘链接&#xff1a; 宝可梦肉鸽 免安装中文版 名称&#xff1a;宝可梦肉鸽 PC/手机双端 多种存档 全闪光 无限金币 全宝可梦解锁 免安装中文版 描述&#xff1a;宝可梦肉鸽修改版是一款非常受欢迎的口袋妖怪系列&#xff0c;游戏拥有许多独特的妖怪和玩法。在游戏中&#…

Linux 下的网络编程

1、目的实现不同主机上进程间的通信。2、问题主机与主机之间在物理层面必须互联互通。进程与进程在软件层面必须互联互通。IP地址&#xff1a;计算机的软件地址&#xff0c;用来标识计算机设备。MAC地址&#xff1a;计算机的硬件地址&#xff08;固定&#xff09;。网络的端口号…

Go语言在边缘计算中的网络编程实践:从入门到精通

一、引言 在数字化浪潮席卷全球的今天&#xff0c;边缘计算如同一股清流&#xff0c;正在重新定义我们对网络架构的理解。想象一下&#xff0c;当你在自动驾驶汽车中需要毫秒级响应&#xff0c;或者在偏远工厂中需要实时处理传感器数据时&#xff0c;传统的云计算模式就像是&qu…

ASPICE过程能力确定——度量框架

&#x1f697;【汽车人必看】ASPICE能力评估核心&#xff1a;度量框架全解析&#xff5c;90%工程师都搞不懂的评分规则&#xff01;&#x1f50d; 为什么你的ASPICE评估总卡在L2&#xff1f;——揭秘6大能力等级背后的评分逻辑&#xff0c;附提升秘籍&#xff01;&#x1f525;…

机器学习在量化中的应用

一、核心应用场景在因子研究中&#xff0c;scikit-learn 主要解决以下几类问题&#xff1a;因子预处理与标准化&#xff1a;StandardScaler, RobustScaler因子有效性分析&#xff1a;LinearRegression (IC分析)降维与因子合成&#xff1a;PCA, FactorAnalysis机器学习预测模型&…

RabbitMQ:消息转化器

目录一、基本概述二、如何处理一、基本概述 在RabbitMQ中&#xff0c;一般情况下传递字符串会被正常解析&#xff0c;如果传递的是一个Object类型或者是一个对象类型的时候&#xff0c;RabbitMQ会将其自动转化为字节码发送&#xff0c;这不利于我们的读取个解析。 二、如何处…

【Protues仿真】基于AT89C52单片机的LCD液晶显示屏显示控制

目录 1 LM016L液晶显示模块 1.1 基本参数 1.2 引脚定义 1.3硬件连接示例&#xff08;AT89C52&#xff09; 1.4 常用指令集&#xff08;HD44780 子集&#xff09; 1.5 常见问题与注意事项 1.8 结论 2 LM016L液晶显示模块控制电路原理图 3 LM016L液晶显示模块控制程序 …

孤独伤感视频素材哪里找?分享热门伤感短视频素材资源网站

你是不是也经常在抖音上刷到很火的伤感视频&#xff0c;那么伤感视频素材都在哪里可以下载呢&#xff1f;作为一名从业多年的视频剪辑师&#xff0c;今天就跟大家聊聊那些可以下载伤感素材高清无水印的网站&#xff0c;如果你也在苦苦找寻伤感素材&#xff0c;快来看看吧&#…

笔记本怎么才能更快散热?

一、“物理降温法”​▪️ 垫高高&#xff01;别让底部 “窒息”​笔记本底部全是进风口&#xff0c;放床上 / 沙发上会被堵住&#xff01;垫点东西拉开底部空间&#xff0c;高度 1-2cm。​▪️ 给风扇 “松绑”​按「CtrlShiftEsc」打开任务管理器&#xff0c;点 “进程”&…