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

SpringAI1.0.1实战教程:避坑指南25年8月最新版

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.dtcms.com/a/343477.html

相关文章:

  • 近端策略优化算法PPO的核心概念和PyTorch实现详解
  • Typescript入门-函数讲解
  • 创建一个springboot starter页面
  • LG P2617 Dynamic Rankings Solution
  • 1688 商品详情接口数据全解析(1688.item_get)
  • 关于从零开始写一个TEE OS
  • 如何安装 VMware Workstation 17.5.1?超简单步骤(附安装包下载)
  • Building Systems with the ChatGPT API 使用 ChatGPT API 搭建系统(第四章学习笔记及总结)
  • 一文讲清楚:场景、痛点、需求
  • mainMem.useNamedFile = “FALSE“ 的效果
  • UE5多人MOBA+GAS 52、下载源码构建引擎
  • 如何处理项目中棘手的依赖版本冲突问题
  • 软考中级【网络工程师】第6版教材 第3章 局域网 (下)
  • 构造参数注入解决循环依赖问题
  • 射频电路的完整性简略
  • rt-thread使用sfud挂载qspi flash的trace分析
  • Linux ELF二进制文件数字签名工具:原理与设计思路(C/C++代码实现)
  • SQL聚合情景解读
  • 【笔记】Facefusion3.3.2 之 NSFW 检测屏蔽测试
  • 代码随想录算法训练营27天 | ​​56. 合并区间、738.单调递增的数字、968.监控二叉树(提高)
  • 机器学习6
  • 机器学习-聚类算法
  • 告别研发乱局,决胜项目先机——全星APQP系统,为汽车部件制造商量身打造的数字化研发管理引擎
  • GPT5 / 深度研究功能 无法触发
  • 4.Shell脚本修炼手册---变量进阶知识
  • 加速你的故障排查:使用 Elasticsearch 构建家电手册的 RAG 应用
  • 如何实现文档处理全流程自动化?
  • 如何在日常开发中高效使用 Copilot
  • 无人机高科技,翱翔未来新天地
  • 对比学习与先验知识引导的特征提取网络在胶质瘤高风险复发区域预测中的应用|文献速递-深度学习人工智能医疗图像