当前位置: 首页 > 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.dtcms.com/a/274228.html

相关文章:

  • TCP服务端处理HTT
  • V少JS基础班之第七弹
  • 【Linux】GDB/CGDB 调试器学习笔记
  • 【Git】git的回退功能
  • map数据结构在Golang中是无序的,并且键值对的查找效率较高的原因
  • pyQt基础4(对话框)
  • 力扣 hot100 Day41
  • OS16.【Linux】冯依诺曼体系结构和操作系统的浅层理解
  • 深度学习×第8卷:优化器与训练流程进阶——她开始跑起来,学着一次次修正自己
  • 聊聊AI大模型的上下文工程(Context Engineering)
  • linux网络编程之单reactor模型(一)
  • 渗透测试之木马后门实验
  • 笔记 | 理解C/汇编中的数组元素访问
  • UNIX 域套接字实现本地进程间通信
  • 【React Native】样式、网络请求和Loading
  • Hadoop 用户入门指南:驾驭大数据的力量
  • 【React Native】原生组件
  • Dify 1.5.0,1.5.1,1.6.0 新特性
  • 小旺AI截图×英特尔强强联合:AIPC生态开启智能生产力新纪元
  • C++设计秘籍:为什么所有参数都需类型转换时,非成员函数才是王道?
  • 基于强化学习的智能推荐系统优化实践
  • 继续Java的jpackage模块打包Linux可执行程序(包含第三方非模块化包)
  • 4G Cat.1 时代,如何选对 DTU?
  • IoC 是如何为 Spring 的其他核心功能(如 AOP、事务管理)提供基础支持的
  • openpilot:为您的汽车插上智能驾驶的翅膀
  • CV目标检测中的LetterBox操作
  • Swift 解 LeetCode 324:一步步实现摆动排序 II,掌握数组重排的节奏感
  • 使用自然语言体验对话式MySQL数据库运维
  • Claude Code:完爆 Cursor 的编程体验
  • UI前端大数据处理新趋势:基于边缘计算的数据处理与响应