
经过上一篇 LangChain4j - RAG落地实战, 已经了解了极简版 RAG,那么本篇呢,继续延续上篇内容开展。
下面来试试标准版 RAG 实现,为了更好的效果,我们需要:
在 Spring Boot 配置文件中添加 Embedding 模型配置,使用阿里云提供的 text-embedding-v4 模型:
langchain4j:
community:
dashscope:
chat-model:
model-name: qwen-max
api-key: <You API Key here>
embedding-model:
model-name: text-embedding-v4
api-key: <You API Key here>
新建 rag.RagConfig,编写 RAG 相关的代码,执行 RAG 的初始流程并返回一个定制的内容检索器 Bean:
/**
* 加载 RAG
*
* @author BNTang
*/
@Configuration
public class RagConfig {
@Resource
private EmbeddingModel qwenEmbeddingModel;
@Resource
private EmbeddingStore<TextSegment> embeddingStore;
@Bean
public ContentRetriever contentRetriever() {
// ------ RAG ------
// 1. 加载文档
List<Document> documents = FileSystemDocumentLoader.loadDocuments("src/main/resources/docs");
// 2. 文档切割:将每个文档按每段进行分割,最大 1000 字符,每次重叠最多 200 个字符
DocumentByParagraphSplitter paragraphSplitter = new DocumentByParagraphSplitter(1000, 200);
// 3. 自定义文档加载器
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.documentSplitter(paragraphSplitter)
// 为了提高搜索质量,为每个 TextSegment 添加文档名称
.textSegmentTransformer(textSegment -> TextSegment.from(
textSegment.metadata().getString("file_name") + "\n" + textSegment.text(),
textSegment.metadata()
))
// 使用指定的向量模型
.embeddingModel(qwenEmbeddingModel)
.embeddingStore(embeddingStore)
.build();
// 加载文档
ingestor.ingest(documents);
// 4. 自定义内容查询器
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(qwenEmbeddingModel)
// 最多 5 个检索结果
.maxResults(5)
// 过滤掉分数小于 0.75 的结果
.minScore(0.75)
.build();
}
}然后在构建 AI Service 时绑定内容检索器:
@Resource
private ContentRetriever contentRetriever;@Bean
public AiCodeHelperService aiCodeHelperService() {
// 设置聊天记忆,最多保留最近 10 条消息
ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
// 构建 AI Service
return AiServices.builder(AiCodeHelperService.class)
.chatModel(qwenChatModel)
.chatMemory(chatMemory)
// RAG 检索增强生成
.contentRetriever(contentRetriever)
.build();
}
修改 AiCodeHelperService 新增 chatWithRag:
@SystemMessage(fromResource = "system-prompt.txt")
Result<String> chatWithRag(String userMessage);
编写单元测试:
@Test
void chatWithRag() {
Result<String> result = aiCodeHelperService.chatWithRag("怎么学习 Java?有哪些常见面试题?");
System.out.println(result.content());
System.out.println(result.sources());
}Debug 运行,能够看到分割的文档片段,部分文档片段有内容重叠:

可以在对话记忆中看到实际发送的、增强后的 Prompt:


回答效果也是符合预期的:

如果这篇文章帮到了你,不妨点个分享给同样需要的朋友吧! 你的每一次支持,都是我持续创作的动力!💪
往期推荐:
序号 | 文章标题 | 链接 |
|---|---|---|
1 | MCP协议爆火揭秘 | 查看详情 |
2 | 轻松配置Cursor玩转MCP | 查看详情 |
3 | Browser-Tool 前端开发神器 | 查看详情 |
4 | AI编码焕新:用Context7 | 查看详情 |
5 | NotebookLM:靠谱知识库 | 查看详情 |
6 | Spring AI 玩转多轮对话 | 查看详情 |
7 | Cursor生成UI,加一步封神 | 查看详情 |
8 | 神器!免费替代Postman | 查看详情 |