Spring AI模块化RAG架构解析:三阶段设计与实现详解
文章目录
-
- 1. 模块化RAG架构全景图
- 2. 预检索阶段:查询优化引擎
-
- 2.1 核心职责
- 2.2 关键组件实现
-
- 2.2.1 查询重写器(Query Rewriter)
- 2.2.2 查询扩展器(Query Expander)
- 2.2.3 路由决策器(Router)
- 3. 检索阶段:知识获取引擎
-
- 3.1 核心职责
- 3.2 关键组件实现
-
- 3.2.1 混合检索器(HybridRetriever)
- 3.2.2 元数据过滤器(MetadataFilter)
- 4. 后检索阶段:答案精炼引擎
-
- 4.1 核心职责
- 4.2 关键组件实现
-
- 4.2.1 神经排序器(NeuralReranker)
- 4.2.2 证据合成器(EvidenceSynthesizer)
- 5. 三阶段协同工作流
-
- 5.1 完整处理流程示例
- 5.2 Spring AI配置示例
- 6. 高级优化策略
-
- 6.1 动态阶段跳过机制
- 6.2 反馈驱动优化
- 7. 生产环境考量
-
- 7.1 性能监控指标
- 7.2 容错设计
检索增强生成(RAG)系统正成为企业级AI应用的核心架构,Spring AI提出的模块化RAG架构通过清晰的阶段划分和标准化接口,为开发者提供了高度灵活的实现框架。本文将深入剖析该架构的核心设计,并详细讲解预检索、检索和后检索三个阶段的具体职责与技术实现。
1. 模块化RAG架构全景图
Spring AI的模块化RAG架构采用管道过滤器模式,将整个流程分解为三个明确定义的阶段,每个阶段包含多个可插拔组件:
#mermaid-svg-FMIWlNAKZofGhckT {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-FMIWlNAKZofGhckT .error-icon{fill:#552222;}#mermaid-svg-FMIWlNAKZofGhckT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FMIWlNAKZofGhckT .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-FMIWlNAKZofGhckT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FMIWlNAKZofGhckT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FMIWlNAKZofGhckT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FMIWlNAKZofGhckT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FMIWlNAKZofGhckT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FMIWlNAKZofGhckT .marker.cross{stroke:#333333;}#mermaid-svg-FMIWlNAKZofGhckT svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FMIWlNAKZofGhckT .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FMIWlNAKZofGhckT .cluster-label text{fill:#333;}#mermaid-svg-FMIWlNAKZofGhckT .cluster-label span{color:#333;}#mermaid-svg-FMIWlNAKZofGhckT .label text,#mermaid-svg-FMIWlNAKZofGhckT span{fill:#333;color:#333;}#mermaid-svg-FMIWlNAKZofGhckT .node rect,#mermaid-svg-FMIWlNAKZofGhckT .node circle,#mermaid-svg-FMIWlNAKZofGhckT .node ellipse,#mermaid-svg-FMIWlNAKZofGhckT .node polygon,#mermaid-svg-FMIWlNAKZofGhckT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FMIWlNAKZofGhckT .node .label{text-align:center;}#mermaid-svg-FMIWlNAKZofGhckT .node.clickable{cursor:pointer;}#mermaid-svg-FMIWlNAKZofGhckT .arrowheadPath{fill:#333333;}#mermaid-svg-FMIWlNAKZofGhckT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FMIWlNAKZofGhckT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FMIWlNAKZofGhckT .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-FMIWlNAKZofGhckT .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-FMIWlNAKZofGhckT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FMIWlNAKZofGhckT .cluster text{fill:#333;}#mermaid-svg-FMIWlNAKZofGhckT .cluster span{color:#333;}#mermaid-svg-FMIWlNAKZofGhckT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FMIWlNAKZofGhckT :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 后检索阶段 检索阶段 预检索阶段 结果重排序 证据合成 生成控制 向量检索 关键词搜索 混合检索 查询重写 查询扩展 查询路由 用户提问 预检索阶段 检索阶段 后检索阶段 最终回答
2. 预检索阶段:查询优化引擎
2.1 核心职责
- 意图澄清:解析用户问题的潜在意图
- 查询优化:提升检索命中率的关键改造
- 路由决策:确定最合适的检索路径
2.2 关键组件实现
2.2.1 查询重写器(Query Rewriter)
public interface QueryRewriter { String rewrite(String originalQuery, RewriteContext context);}@Servicepublic class AISemanticRewriter implements QueryRewriter { private final ChatClient chatClient; @Override public String rewrite(String query, RewriteContext ctx) { String prompt = \"\"\" 请重写以下查询以优化检索效果: 原始查询: %s 用户上下文: %s 只返回重写后的查询 \"\"\".formatted(query, ctx.getUserProfile()); return chatClient.call(prompt).getResult().getOutput().getContent(); }}
2.2.2 查询扩展器(Query Expander)
public class HybridQueryExpander { private final SynonymExpander synonymExpander; private final VectorExpander vectorExpander; public String expand(String query) { // 基于同义词的扩展 String synonymExpanded = synonymExpander.expand(query); // 基于向量相似的扩展 String vectorExpanded = vectorExpander.expand(query); return mergeExpansions(query, synonymExpanded, vectorExpanded); }}
2.2.3 路由决策器(Router)
public class ContentTypeRouter { public RouteDecision route(String query) { String prompt = \"\"\" 判断查询最适合的检索类型: 1. VECTOR - 语义搜索(如概念性问题) 2. KEYWORD - 精确匹配(如产品代码) 3. HYBRID - 混合模式 查询: %s 只返回类型名称 \"\"\".formatted(query); String routeType = chatClient.call(prompt).getResult().getOutput().getContent(); return new RouteDecision(routeType); }}
3. 检索阶段:知识获取引擎
3.1 核心职责
- 多模态检索:支持文本、向量、结构化数据等多种形式
- 混合搜索:结合传统关键词与向量搜索优势
- 初步过滤:应用基础相关性阈值
3.2 关键组件实现
3.2.1 混合检索器(HybridRetriever)
public class HybridRetriever implements Retriever { private final VectorStore vectorStore; private final KeywordSearchEngine keywordEngine; @Override public List<Document> retrieve(String query) { // 并行执行两种检索 List<Document> vectorResults = vectorStore.similaritySearch(query); List<Document> keywordResults = keywordEngine.search(query); // 融合排序 return new ReciprocalRankFusion() .fuse(vectorResults, keywordResults); }}
3.2.2 元数据过滤器(MetadataFilter)
public class TemporalFilter implements Filter { @Override public List<Document> filter(List<Document> docs, FilterContext ctx) { return docs.stream() .filter(doc -> { Instant docTime = doc.getMetadata().get(\"timestamp\"); return docTime.isAfter(ctx.getTimeThreshold()); }) .collect(Collectors.toList()); }}
4. 后检索阶段:答案精炼引擎
4.1 核心职责
- 结果精排:基于多维度特征重新排序
- 证据组织:构建生成阶段的参考依据
- 生成控制:约束LLM的输出形式
4.2 关键组件实现
4.2.1 神经排序器(NeuralReranker)
public class CrossEncoderReranker implements Reranker { private final CrossEncoderModel model; @Override public List<Document> rerank(String query, List<Document> docs) { List<Pair<String, String>> queryDocPairs = docs.stream() .map(doc -> Pair.of(query, doc.getContent())) .collect(Collectors.toList()); float[] scores = model.predict(queryDocPairs); // 组合文档与得分 return IntStream.range(0, docs.size()) .mapToObj(i -> new ScoredDocument(docs.get(i), scores[i])) .sorted(Comparator.reverseOrder()) .map(ScoredDocument::getDocument) .collect(Collectors.toList()); }}
4.2.2 证据合成器(EvidenceSynthesizer)
public class TreeBasedSynthesizer implements EvidenceSynthesizer { @Override public String synthesize(String query, List<Document> docs) { String prompt = \"\"\" 基于以下文档提取关键证据: 问题: %s 文档: %s 要求: 1. 去除矛盾信息 2. 保留数据来源 3. 输出Markdown格式 \"\"\".formatted(query, joinDocuments(docs)); return chatClient.call(prompt).getResult().getOutput().getContent(); }}
5. 三阶段协同工作流
5.1 完整处理流程示例
#mermaid-svg-3webTKPJBq4Vxlwv {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3webTKPJBq4Vxlwv .error-icon{fill:#552222;}#mermaid-svg-3webTKPJBq4Vxlwv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3webTKPJBq4Vxlwv .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-3webTKPJBq4Vxlwv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3webTKPJBq4Vxlwv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3webTKPJBq4Vxlwv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3webTKPJBq4Vxlwv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3webTKPJBq4Vxlwv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3webTKPJBq4Vxlwv .marker.cross{stroke:#333333;}#mermaid-svg-3webTKPJBq4Vxlwv svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3webTKPJBq4Vxlwv .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3webTKPJBq4Vxlwv text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-3webTKPJBq4Vxlwv .actor-line{stroke:grey;}#mermaid-svg-3webTKPJBq4Vxlwv .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-3webTKPJBq4Vxlwv .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-3webTKPJBq4Vxlwv #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-3webTKPJBq4Vxlwv .sequenceNumber{fill:white;}#mermaid-svg-3webTKPJBq4Vxlwv #sequencenumber{fill:#333;}#mermaid-svg-3webTKPJBq4Vxlwv #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-3webTKPJBq4Vxlwv .messageText{fill:#333;stroke:#333;}#mermaid-svg-3webTKPJBq4Vxlwv .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3webTKPJBq4Vxlwv .labelText,#mermaid-svg-3webTKPJBq4Vxlwv .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-3webTKPJBq4Vxlwv .loopText,#mermaid-svg-3webTKPJBq4Vxlwv .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-3webTKPJBq4Vxlwv .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-3webTKPJBq4Vxlwv .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-3webTKPJBq4Vxlwv .noteText,#mermaid-svg-3webTKPJBq4Vxlwv .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-3webTKPJBq4Vxlwv .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3webTKPJBq4Vxlwv .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3webTKPJBq4Vxlwv .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-3webTKPJBq4Vxlwv .actorPopupMenu{position:absolute;}#mermaid-svg-3webTKPJBq4Vxlwv .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-3webTKPJBq4Vxlwv .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-3webTKPJBq4Vxlwv .actor-man circle,#mermaid-svg-3webTKPJBq4Vxlwv line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-3webTKPJBq4Vxlwv :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} User PreRetrieval Retrieval PostRetrieval LLM \"如何预防感冒?\" 重写为\"感冒预防措施\" 扩展为\"感冒预防 增强免疫力方法\" 优化后的查询 向量搜索(0.8权重) 关键词搜索(0.2权重) 混合结果(FRF算法) 20篇相关文档 基于时效性重排序 提取关键证据 问题+结构化证据 \"预防感冒的5个科学方法...\" User PreRetrieval Retrieval PostRetrieval LLM
5.2 Spring AI配置示例
spring: ai: rag: pre-retrieval: rewriters: - type: semantic temperature: 0.3 - type: spelling routers: - type: content-based retrieval: type: hybrid vector: similarity-threshold: 0.7 keyword: boost-fields: [\"title^2\", \"content\"] post-retrieval: reranker: type: cross-encoder model: cross-encoder/ms-marco-MiniLM-L-6-v2 synthesizer: type: tree-summary
6. 高级优化策略
6.1 动态阶段跳过机制
public class SmartPipeline extends DefaultRagPipeline { @Override public RagResponse run(RagRequest request) { // 检测是否可跳过检索(如FAQ直接匹配) if (preRetrievalAnalyzer.canSkipRetrieval(request)) { return generateDirectResponse(request); } // 正常执行三阶段流程 return super.run(request); }}
6.2 反馈驱动优化
@EventListenerpublic void onUserFeedback(FeedbackEvent event) { // 根据用户正负反馈调整各阶段参数 optimizationEngine.adjustParameters( event.getQuery(), event.getFeedback(), event.getResponse() );}
7. 生产环境考量
7.1 性能监控指标
7.2 容错设计
public class FallbackRagPipeline implements RagPipeline { private final List<RagPipeline> pipelines; @Override public RagResponse run(RagRequest request) { for (RagPipeline pipeline : pipelines) { try { return pipeline.run(request); } catch (Exception e) { log.warn(\"Pipeline failed\", e); } } return basicFallbackResponse(request); }}
Spring AI的模块化RAG架构通过标准化的阶段划分和接口设计,使开发者能够灵活组合最新技术组件。这种架构特别适合需要快速迭代的AI应用场景,三个阶段的明确分工也使得性能优化和问题排查更加有的放矢。随着RAG技术的演进,该架构可无缝集成诸如动态检索、多跳推理等高级能力。