共计 2816 个字符,预计需要花费 8 分钟才能阅读完成。
背景分析
传统生成式模型(如 GPT 系列)虽然在文本生成上表现出色,但存在两个明显痛点:

- 知识更新滞后 :模型训练完成后,其知识库即固定,无法实时吸收新信息。例如 2023 年发布的模型可能不知道 2024 年的新闻事件。
- 事实性错误 :模型可能生成看似合理但实际错误的回答(即 ” 幻觉 ” 现象)。
RAG(Retrieval-Augmented Generation)通过结合检索系统与生成模型,有效解决了这些问题:
- 实时性 :检索模块从动态更新的知识库中获取最新资料
- 准确性 :生成结果基于检索到的真实文档,大幅降低幻觉风险
架构设计
在 AgentScope 框架中的 RAG 系统工作流程:
flowchart LR
A[用户提问] --> B{检索模块}
B -->| 向量搜索 | C[(向量数据库)]
C --> D[相关文档]
D --> E{生成模块}
E --> F[最终回答]
关键组件说明:
- 检索模块 :将用户问题转换为向量,从数据库查找相似文档
- 增强模块 :将检索结果作为上下文注入生成模型
- 生成模块 :基于上下文生成最终回答
核心实现
检索模块实现
以 Milvus 为例的 Java 集成方案:
// 初始化 Milvus 客户端
public class VectorStoreService {
private final MilvusClient client;
@PostConstruct
public void init() {ConnectParam connectParam = ConnectParam.newBuilder()
.withHost("localhost")
.withPort(19530)
.build();
this.client = new MilvusServiceClient(connectParam);
}
public List<String> searchSimilarDocs(float[] queryEmbedding, int topK) {List<Float> vector = Arrays.stream(queryEmbedding)
.boxed().collect(Collectors.toList());
SearchParam searchParam = SearchParam.newBuilder()
.withCollectionName("knowledge_base")
.withVectorFieldName("embedding")
.withVectors(Collections.singletonList(vector))
.withTopK(topK)
.build();
SearchResultsWrapper results = client.search(searchParam);
return results.getIDScore(0).stream()
.map(idScore -> getDocContentById(idScore.getLongID()))
.collect(Collectors.toList());
}
}
增强模块技巧
有效的提示工程模板示例:
根据以下上下文回答问题:{context}
问题:{question}
回答时请:1. 严格基于上下文内容
2. 如上下文未提及,回答 "根据现有资料无法确定"
3. 保持回答简洁专业
完整流水线示例
Spring Boot 控制器实现:
@RestController
@RequiredArgsConstructor
public class RagController {
private final EmbeddingService embeddingService;
private final VectorStoreService vectorStore;
private final GenerationService generationService;
@PostMapping("/ask")
public ResponseEntity<String> generateAnswer(@RequestBody QuestionRequest request) {
try {
// 1. 获取问题向量
float[] embedding = embeddingService.getEmbedding(request.question());
// 2. 检索相关文档
List<String> contexts = vectorStore.searchSimilarDocs(embedding, 3);
// 3. 构造提示词
String prompt = buildPrompt(contexts, request.question());
// 4. 生成最终回答
String answer = generationService.generate(prompt);
return ResponseEntity.ok(answer);
} catch (Exception e) {log.error("RAG 处理失败", e);
return ResponseEntity.internalServerError().build();
}
}
}
性能优化
缓存策略
// 使用 Caffeine 缓存问题向量
@Bean
public Cache<String, float[]> embeddingCache() {return Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(1, TimeUnit.HOURS)
.build();}
异步处理
// 使用 CompletableFuture 并行处理
List<CompletableFuture<String>> futures = contexts.stream()
.map(context -> CompletableFuture.supplyAsync(() -> processSingleContext(context, question),
executorService))
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
避坑指南
常见问题及解决方案:
- 检索偏差 :
- 现象:总是返回相同类型的文档
-
解决:调整相似度阈值,增加多样性采样
-
上下文过长 :
- 现象:生成模型忽略部分上下文
- 解决:实现智能截断算法,保留最相关段落
效果评估
建议采用三个维度的评估指标:
- 检索质量 :
- 查全率 @K
-
平均相似度得分
-
生成质量 :
- BLEU/ROUGE 分数
-
人工评估准确率
-
系统性能 :
- 端到端延迟
- 吞吐量 (QPS)
总结
在 AgentScope 中实现 Java RAG 系统时,建议分阶段推进:
- 先搭建最小可行版本验证核心流程
- 逐步添加缓存、异步等优化手段
- 最后完善监控和评估体系
实际项目中我们发现,当检索模块准确率超过 85% 时,系统整体效果会有显著提升。建议持续迭代优化检索策略,这是影响最终效果的关键因素。
正文完
发表至: 技术分享
近三天内
