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

spring-boot项目集成spring-ai

引入相关依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-openai</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-vector-store-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-ollama</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client</artifactId></dependency><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.13.4</version></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-advisors-vector-store</artifactId></dependency>

先做基础的向量库管理

@Component
public class VectorStoreUtil {@Autowiredprivate VectorStore vectorStore;@Autowiredprivate EmbeddingModel embeddingModel;/*** 将单个文档添加到向量索引中* @param content 文本内容*/public void insert(String content) {Document document = new Document(content);vectorStore.add(List.of(document));}/*** 批量添加多个文档*/public void insertBatch(List<String> contents) {if (contents == null || contents.isEmpty()) {System.out.println("Warning: insertBatch called with empty content list, skipping.");return;}List<Document> docs = contents.stream().map(Document::new).toList();vectorStore.add(docs);}public List<Document> query(String content) {List<Document> results = vectorStore.similaritySearch(SearchRequest.builder().topK(1).query(content).build());return results;}
//    获取向量public float[] getEmbedding(String content){return embeddingModel.embed(content);}}

做记忆化和RAG相关的advisor

@Configuration
public class ChatAgentConfig {@Beanpublic MessageChatMemoryAdvisor memoryAdvisor(ChatMemory chatMemory) {return MessageChatMemoryAdvisor.builder(chatMemory).build();}@Beanpublic QuestionAnswerAdvisor ragAdvisor(VectorStore vectorStore) {return QuestionAnswerAdvisor.builder(vectorStore).searchRequest(SearchRequest.builder().similarityThreshold(0.6d).topK(5).build()).build();}
}

写运行配置

spring:elasticsearch:uris: http://localhost:9200username: elasticpassword: changemedata:redis:host: "localhost"port: 6379database: 0# username:# password:connect-timeout: 5stimeout: 5sai:anthropic:enabled: falsemcp:client:version: 1.0.0request-timeout: 60stype: SYNCtoolcallback:enabled: truestdio:servers-configuration:  file:./mcp-servers.jsonvectorstore:elasticsearch:initialize-schema: trueindex-name: custom-indexdimensions: 768similarity: cosineopenai:base-url: api-key: chat:options:model: temperature: 0.7ollama:base-url: http://localhost:11434embedding:options:model: nomic-embed-textmodel:embedding: ollama

最后完成我们的终极AI对话类

@Component
public class SuperAiAgent {private final ChatClient chatClient;//对话器private final ToolCallbackProvider toolCallbackProvider;//MCP工具private final QuestionAnswerAdvisor ragAdvisor;//RAG@Autowiredprivate List<McpSyncClient> mcpSyncClients;@Autowiredpublic SuperAiAgent(@Qualifier("openAiChatModel") ChatModel chatModel,MessageChatMemoryAdvisor memoryAdvisor,QuestionAnswerAdvisor ragAdvisor,ToolCallbackProvider toolCallbackProvider) {this.chatClient = ChatClient.builder(chatModel).defaultAdvisors(memoryAdvisor).build();//自带对话idthis.toolCallbackProvider = toolCallbackProvider;this.ragAdvisor = ragAdvisor;}String sysPrompt="";public String ask(String question, Object conversationId, boolean useRag, boolean useTools) {var prompt = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId));prompt.messages(new SystemMessage(sysPrompt));if (useRag) {prompt.advisors(ragAdvisor); // 动态启用 RAG}if (useTools) {prompt.toolCallbacks(toolCallbackProvider); // 启用 MCP 工具调用}try {return prompt.user(question).call().content();} catch (ToolExecutionException e) {// 工具调用异常,打印日志或返回默认内容System.err.println("工具调用异常: " + e.getMessage());// 返回模型基础回答或自定义错误提示// 这里可以调用不带工具的对话或者返回固定内容return "工具调用失败,已忽略错误。";} catch (Exception e) {// 其它异常处理e.printStackTrace();return "对话处理异常,请稍后再试。";}}public String ask(String question, Object conversationId, boolean useRag, boolean useTools, Set<String>mcpList) {var prompt = chatClient.prompt().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId));if (useRag) {prompt.advisors(ragAdvisor); // 动态启用 RAG}if (useTools) {List<McpSyncClient>clients = new ArrayList<>();for(var client : mcpSyncClients) {if(mcpList.contains(client.getServerInfo().name())){clients.add(client);}}ToolCallbackProvider provider = new SyncMcpToolCallbackProvider(clients);prompt.toolCallbacks(provider);}try {return prompt.user(question).call().content();} catch (ToolExecutionException e) {// 工具调用异常,打印日志或返回默认内容System.err.println("工具调用异常: " + e.getMessage());// 返回模型基础回答或自定义错误提示// 这里可以调用不带工具的对话或者返回固定内容return "工具调用失败,已忽略错误。";} catch (Exception e) {// 其它异常处理e.printStackTrace();return "对话处理异常,请稍后再试。";}}
}
http://www.lryc.cn/news/585657.html

相关文章:

  • 基于k8s环境下pulsar高可用测试和扩缩容(下)
  • Web攻防-SSTI服务端模版注入利用分类语言引擎数据渲染项目工具挖掘思路
  • 华为认证笔试考试中心/VUE考场考试规则与环境欣赏
  • 智慧水文站系统:实时监控、全要素监测与AI辅助
  • 爬虫练习1
  • 数据库报错:Column ‘xxx‘ in field list is ambiguous
  • pyQt基础4(对话框)
  • JAX study notes[16]
  • Java项目中图片加载路径问题解析
  • Python Day10
  • LLM场景下的强化学习【GRPO】
  • Spring Boot整合MyBatis+MySQL实战指南(Java 1.8 + 单元测试)
  • 上位机知识篇---端口
  • latex格式中插入eps格式的图像的编译命令
  • 异步复习(线程)
  • 【第四节】ubuntu server安装docker
  • 从0开始学习R语言--Day44--LR检验
  • 文章发布易优CMS(Eyoucms)网站技巧
  • 企业IT管理——医院数据备份与存储制度模板
  • Linux自动化构建工具(一)
  • 多表查询-2-多表查询概述
  • 蔚来测开一面:HashMap从1.7开始到1.8的过程,既然都解决不了并发安全问题,为什么还要进一步解决环形链表的问题?
  • 前端面试专栏-算法篇:23. 图结构与遍历算法
  • USB一线连多屏?Display Link技术深度解析
  • React中Redux基础和路由介绍
  • 适配多场景,工业显示器让操作更高效
  • 前端八股-promise
  • Spring的事务控制——学习历程
  • C++设计秘籍:为什么所有参数都需类型转换时,非成员函数才是王道?
  • Python-正则表达式-信息提取-滑动窗口-数据分发-文件加载及分析器-浏览器分析-学习笔记