检索增强生成(RAG)系统正成为企业级AI应用的核心架构,Spring AI提出的模块化RAG架构通过清晰的阶段划分和标准化接口,为开发者提供了高度灵活的实现框架。本文将深入剖析该架构的核心设计,并详细讲解预检索、检索和后检索三个阶段的具体职责与技术实现。
1. [模块化]RAG架构全景图
Spring AI的模块化RAG架构采用管道过滤器模式,将整个流程分解为三个明确定义的阶段,每个阶段包含多个可插拔组件:
后检索阶段
检索阶段
预检索阶段
结果重排序
证据合成
生成控制
向量检索
关键词搜索
混合检索
查询重写
查询扩展
查询路由
用户提问
预检索阶段
检索阶段
后检索阶段
最终回答
2. 预检索阶段:查询优化引擎
2.1 核心职责
- 意图澄清:解析用户问题的潜在意图
- 查询优化:提升检索命中率的关键改造
- 路由决策:确定最合适的检索路径
2.2 关键组件实现
2.2.1 查询重写器(Query Rewriter)
typescript
public interface QueryRewriter {
String rewrite(String originalQuery, RewriteContext context);
}
@Service
public 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();
}
}
AI写代码java
运行
1234567891011121314151617181920
2.2.2 查询扩展器(Query Expander)
arduino
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);
}
}
AI写代码java
运行
1234567891011121314
2.2.3 路由决策器(Router)
ini
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);
}
}
AI写代码java
运行
123456789101112131415
3. 检索阶段:知识获取引擎
3.1 核心职责
- 多模态检索:支持文本、向量、结构化数据等多种形式
- 混合搜索:结合传统关键词与向量搜索优势
- 初步过滤:应用基础相关性阈值
3.2 关键组件实现
3.2.1 混合检索器(HybridRetriever)
java
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);
}
}
AI写代码java
运行
123456789101112131415
3.2.2 元数据[过滤器]
kotlin
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());
}
}
AI写代码java
运行
1234567891011
4. 后检索阶段:答案精炼引擎
4.1 核心职责
- 结果精排:基于多维度特征重新排序
- 证据组织:构建生成阶段的参考依据
- 生成控制:约束LLM的输出形式
4.2 关键组件实现
4.2.1 神经排序器(NeuralReranker)
scss
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());
}
}
AI写代码java
运行
12345678910111213141516171819
4.2.2 证据合成器(EvidenceSynthesizer)
ini
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();
}
}
AI写代码java
运行
1234567891011121314151617
5. 三阶段协同工作流
5.1 完整处理流程示例
UserPreRetrievalRetrievalPostRetrievalLLM"如何预防感冒?"重写为"感冒预防措施"扩展为"感冒预防 增强免疫力方法"优化后的查询向量搜索(0.8权重)关键词搜索(0.2权重)混合结果(FRF算法)20篇相关文档基于时效性重排序提取关键证据问题+结构化证据"预防感冒的5个科学方法..."UserPreRetrievalRetrievalPostRetrievalLLM
5.2 Spring AI配置示例
yaml
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
AI写代码yaml
123456789101112131415161718192021222324
6. 高级优化策略
6.1 动态阶段跳过机制
scala
public class SmartPipeline extends DefaultRagPipeline {
@Override
public RagResponse run(RagRequest request) {
// 检测是否可跳过检索(如FAQ直接匹配)
if (preRetrievalAnalyzer.canSkipRetrieval(request)) {
return generateDirectResponse(request);
}
// 正常执行三阶段流程
return super.run(request);
}
}
AI写代码java
运行
123456789101112
6.2 反馈驱动优化
csharp
@EventListener
public void onUserFeedback(FeedbackEvent event) {
// 根据用户正负反馈调整各阶段参数
optimizationEngine.adjustParameters(
event.getQuery(),
event.getFeedback(),
event.getResponse()
);
}
AI写代码java
运行
123456789
7. 生产环境考量
7.1 性能监控指标
阶段 | 关键指标 | 预警阈值 |
---|---|---|
预检索 | 平均延迟 | >200ms |
检索 | 召回率@10 | <0.6 |
后检索 | 精排NDCG | <0.7 |
7.2 容错设计
kotlin
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);
}
}
AI写代码java
运行
123456789101112131415
Spring AI的模块化RAG架构通过[标准化]的阶段划分和接口设计,使开发者能够灵活组合最新技术组件。这种架构特别适合需要快速迭代的AI应用场景,三个阶段的明确分工也使得性能优化和问题排查更加有的放矢。随着RAG技术的演进,该架构可无缝集成诸如动态检索、多跳推理等高级能力。