Spring AI 系列(三):RAG 开发必知——两种 Advisor 到底怎么选?附完整代码实现
Spring AI 提供了对常见 RAG 流程的开箱支持,通过 Advisor API 实现,向量数据库存储着AI模型所不知道的数据,当用户提问时,Advisor 会向向量数据库查询与用户问题相关的文档,将检索结果附加到用户文本中,然后通过 AI 大模型推理生成最终回答。
在 RAG 流程中,有两种 Advisor:QuestionAnswerAdvisor 和 RetrievalAugmentationAdvisor。
QuestionAnswerAdvisor
当用户提出问题时,QuestionAnswerAdvisor 会帮助系统从已有的知识库或数据库中检索答案,并将其返回给用户,其核心目的是将用户的问题与知识库中的答案进行匹配,提供答案。QuestionAnswerAdvisor 侧重问答处理,通过理解和分析用户的问题,找到最合适的答案。
RetrievalAugmentationAdvisor
当需要从大型数据库或知识库中检索信息时,RetrievalAugmentationAdvisor 会在检索请求前后插入增强逻辑。例如,在查询过程中,RetrievalAugmentationAdvisor 可以自动加入额外的上下文信息(如用户的历史查询、偏好、领域知识等),以提高检索结果的相关性和准确性。RetrievalAugmentationAdvisor 侧重信息检索,通过增强检索条件和上下文信息来优化查询过程。
备注:Advisor(顾问)是 Spring AI 中用于增强方法执行逻辑的组件,类似于一个拦截器,通过 Advisor,可以在方法执行前后插入自定义逻辑,从而提升代码的可扩展性与灵活性,常用于任务增强、数据预处理等场景。
使用以上两种Advisor时需要在项目maven pom.xml导入如下依赖:
<!-- QuestionAnswerAdvisor 依赖包--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-advisors-vector-store</artifactId></dependency><!-- RetrievalAugmentationAdvisor 依赖包--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-rag</artifactId></dependency>下面通过SpringBoot程序演示两种Advisor的使用方式,该案例中我们将固定的文档片段存入到Milvus向量库,然后通过chatClient 输入问题,分别使用两种Advisor进行检索向量库进行回答。
1. 创建SpringBoot项目
SpringBoot项目命名为SpringAIRAGWithAdvisor,设置使用的JDK为17版本。
2. 在项目中加入如下Maven依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.5.3</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>SpringAIRAGWithAdvisor</artifactId><version>0.0.1-SNAPSHOT</version><name>SpringAIRAGWithAdvisor</name><description>SpringAIRAGWithAdvisor</description><properties><java.version>17</java.version></properties><!-- 导入 Spring AI BOM,用于统一管理 Spring AI 依赖的版本, 引用每个 Spring AI 模块时不用再写 <version>,只要依赖什么模块 Mavens 自动使用 BOM 推荐的版本 --><dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>1.0.0-SNAPSHOT</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Deepseek AI 依赖 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-deepseek</artifactId></dependency><!-- 智普AI 依赖 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-zhipuai</artifactId></dependency><!-- QuestionAnswerAdvisor 依赖包--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-advisors-vector-store</artifactId></dependency><!-- RetrievalAugmentationAdviso 依赖包--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-rag</artifactId></dependency><!-- Milvus VectorStore 依赖包--><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-vector-store-milvus</artifactId></dependency></dependencies><!-- 声明仓库, 用于获取 Spring AI 以及相关预发布版本--><repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></repository><repository><name>Central Portal Snapshots</name><id>central-portal-snapshots</id><url>https://central.sonatype.com/repository/maven-snapshots/</url><releases><enabled>false</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories></project>注意:
- 在该 pom.xml 中引入了
spring-ai-starter-model-zhipuai依赖包用于文档片段转换成向量存入向量库; - 在该 pom.xml 中引入了
spring-ai-starter-model-deepseek依赖包用于 chatClient 聊天。 - 在该 pom.xml 中引入了
spring-ai-advisors-vector-store和spring-ai-rag依赖包,两个依赖包分别为 QuestionAnswerAdvisor 和 RetrievalAugmentationAdvisor 依赖。 - 在该 pom.xml 中引入了
spring-ai-starter-vector-store-milvus依赖包,该依赖为 Milvus VectorStore 依赖包。
3. 配置resources/application.properties
spring.application.name=SpringAIRAGWithAdvisor server.port=8080 ## 使用 智普AI Embedding 模型,需要在pom.xml中引入对应依赖 spring.ai.zhipuai.api-key=d...4 spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas spring.ai.zhipuai.embedding.options.model=embedding-2 ## 配置 Chat Model:Deepseek的基础URL、密钥和使用模型 spring.ai.deepseek.base-url=https://api.deepseek.com spring.ai.deepseek.api-key=sk-8...1 spring.ai.deepseek.chat.options.model=deepseek-chat ## Milvus 配置 spring.ai.vectorstore.milvus.client.host=node2 spring.ai.vectorstore.milvus.client.port=19530 # 默认用户名和密码为 root 和 Milvus spring.ai.vectorstore.milvus.client.token=root:Milvus # 要使用的 Milvus 数据库的名称 spring.ai.vectorstore.milvus.database-name=default # 用于存储 vector 的 Milvus 集合名称 spring.ai.vectorstore.milvus.collection-name=vector_store #是否自动初始化 schema,如:vector_store如果没有会自动创建 spring.ai.vectorstore.milvus.initialize-schema=true # Milvus 集合中要存储的 vector 的维度,默认为1536,要与所使用的 embedding 模型的维度匹配(如:DeepSeek、ZhiPuAI 或其他,都是1024维) spring.ai.vectorstore.milvus.embedding-dimension=10244. 构建两个Rag Advisor和Chat Client
在项目中创建config/AIConfig.java ,该类标记为Configuration类。类中注入QuestionAnswerAdvisor、RetrievalAugmentationAdvisor以及ChatClient,并且每次运行SpringBoot项目时向Milvus中插入指定文档向量数据(如果已存在则不重复插入)。
packagecom.example.springairagwithadvisor.config;importio.milvus.client.MilvusServiceClient;importio.milvus.grpc.GetCollectionStatisticsResponse;importio.milvus.param.R;importio.milvus.param.collection.FlushParam;importio.milvus.param.collection.GetCollectionStatisticsParam;importio.milvus.response.GetCollStatResponseWrapper;importjakarta.annotation.PostConstruct;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;importorg.springframework.ai.deepseek.DeepSeekChatModel;importorg.springframework.ai.document.Document;importorg.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;importorg.springframework.ai.rag.generation.augmentation.ContextualQueryAugmenter;importorg.springframework.ai.rag.retrieval.search.VectorStoreDocumentRetriever;importorg.springframework.ai.vectorstore.SearchRequest;importorg.springframework.ai.vectorstore.VectorStore;importorg.springframework.ai.vectorstore.milvus.MilvusVectorStore;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.List;@ConfigurationpublicclassAIConfig{// 注入 MilvusVectorStore 实例@AutowiredprivateMilvusVectorStorevectorStore;// 从配置文件中读取 Milvus 集合名称@Value("${spring.ai.vectorstore.milvus.collection-name}")privateStringcollectionName;//配置 QuestionAnswerAdvisor,用于问答任务@BeanpublicQuestionAnswerAdvisorquestionAnswerAdvisor(){returnQuestionAnswerAdvisor.builder(vectorStore)// 配置向量搜索的参数,这里设置了相似度阈值为 0.5,返回前 6 个结果.searchRequest(SearchRequest.builder().similarityThreshold(0.5d).topK(6).build()).build();}//配置 RetrievalAugmentationAdvisor,用于增强检索任务@BeanpublicRetrievalAugmentationAdvisorretrievalAugmentationAdvisor(){//VectorStoreDocumentRetriever 负责在向量数据库中根据查询获取最相关的文档//支持根据相似度阈值、top-K(返回前K个最相关文档)和过滤表达式等方式进行精确检索VectorStoreDocumentRetrieverretriever=VectorStoreDocumentRetriever.builder().vectorStore(vectorStore)// 设置向量存储对象.similarityThreshold(0.5)//设置相似度阈值.topK(6)//设置返回前K个最相关文档.build();//ContextualQueryAugmenter 用于增强查询,根据上下文信息生成更具体的查询//支持基于上下文的查询增强,例如根据用户输入的上下文信息生成更具体的查询,提高检索的准确性和效率ContextualQueryAugmentercqa=ContextualQueryAugmenter.builder().allowEmptyContext(true)//允许空上下文.build();//返回 RetrievalAugmentationAdvisor 对象,用于增强检索任务returnRetrievalAugmentationAdvisor.builder().documentRetriever(retriever)// 设置文档检索器.queryAugmenter(cqa)// 设置查询增强器.build();}//配置 ChatClient,初始化聊天客户端@BeanpublicChatClientchatClient(DeepSeekChatModelchatModel){returnChatClient.builder(chatModel).defaultSystem("你是一个助手,回答用户问题是不要提及回复是从上下文信息中获取的,"+"不要回答你不知道的问题,如果你不知道答案,就回答:抱歉,我不清楚这个问题。").build();}/** * @PostConstruct 注解的方法会在 Spring 容器完成依赖注入后自动调用一次,常用于执行初始化逻辑。 */@PostConstructpublicvoidinitVectorData(){System.out.println("初始化向量数据,写入到 Milvus 数据库中...");// 获取 Milvus 客户端实例MilvusServiceClientclient=(MilvusServiceClient)vectorStore.getNativeClient().get();// 获取集合统计信息,查询集合的记录数量R<GetCollectionStatisticsResponse>resp=client.getCollectionStatistics(GetCollectionStatisticsParam.newBuilder().withCollectionName(collectionName).build());// 获取实体数量,即数据行数longrowCount=newGetCollStatResponseWrapper(resp.getData()).getRowCount();System.out.println("Milvus vector_store 中数据数量:"+rowCount);//如果集合没有数据就写入if(rowCount==0){System.out.println("Milvus vector_store 中没有数据,写入...");List<Document>docs=List.of(newDocument("Spring AI 是一个开源 AI 集成项目"),newDocument("Milvus 是一款高性能向量数据库"),newDocument("DeepSeek 是一个开源大语言模型"));//vectorStore.add(docs) 调用时,Spring AI 的 MilvusVectorStore 会使用注入的 EmbeddingModel 将每个 Document 中的文本内容转换成向量并写入vectorStore.add(docs);// 获取 Milvus 客户端并手动调用 flush,刷新索引,确保数据被持久化到 Milvus 数据库中System.out.println("Milvus vector_store 刷新索引...");client.flush(FlushParam.newBuilder().withCollectionNames(List.of(collectionName))// 设置刷新操作的集合名称.build());}}}5. 创建RagController.java
packagecom.example.springairagwithadvisor.controller;importorg.springframework.ai.chat.client.ChatClient;importorg.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;importorg.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;@RestController@RequestMapping("/ai")publicclassRagController{@AutowiredprivateChatClientchatClient;@AutowiredprivateQuestionAnswerAdvisorqaAdvisor;@AutowiredprivateRetrievalAugmentationAdvisorragAdvisor;@GetMapping("/chat1")publicStringask1(@RequestParamStringmessage){returnchatClient.prompt().user(message)//设置使用 QuestionAnswerAdvisor.advisors(List.of(qaAdvisor)).call().content();}@GetMapping("/chat2")publicStringask2(@RequestParamStringmessage){returnchatClient.prompt().user(message)//设置使用 RetrievalAugmentationAdvisor.advisors(List.of(ragAdvisor)).call().content();}}6. 启动Milvus
在linux node2 节点启动Milvus:
#进入 milvus目录cd/software/milvus#启动 Milvusdockercompose up-d7. 启动项目并测试
启动SpringAiRAGWithAdvisor项目,运行主应用类SpringAiragWithAdvisorApplication.java,启动该项目。
在浏览器中输入如下内容进行测试:
# http://localhost:8080/ai/chat1?message=Milvus是什么? Milvus是一款高性能向量数据库。 # http://localhost:8080/ai/chat1?message=今天天气如何? 抱歉,我不清楚这个问题。 # http://localhost:8080/ai/chat2?message=Spring AI是什么? Spring AI 是一个开源 AI 集成项目。 # http://localhost:8080/ai/chat2?message=今天天气如何? 抱歉,我不清楚这个问题。