【LangChain4j学习笔记】LangChain4j RAG 检索增强生成
本文介绍了LangChain4j框架中的RAG(检索增强生成)技术实现。主要内容包括: RAG技术原理:通过结合信息检索和文本生成,解决传统LLM的知识时效性、幻觉问题和私有数据访问等问题。 核心实现步骤: 文本向量化:使用Embedding模型将文本转换为高维向量 向量存储与检索:建立向量数据库并进行相似度搜索 ELP流程:文档提取、加载和处理(分割、向量化、存储) 实际应用: 支持多种文档格式
·
LangChain4j RAG 检索增强生成
学习时间:2026/4/4
技术栈:Spring Boot 4.0.5 + LangChain4j 1.12.2 + 通义千问模型
一、什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合信息检索和文本生成的 AI 技术。
解决的问题
| 问题 | 传统 LLM | RAG 方案 |
|---|---|---|
| 知识时效性 | 训练数据截止 | 可检索实时数据 |
| 幻觉问题 | 可能编造信息 | 基于真实文档回答 |
| 私有数据 | 无法访问 | 可接入私有知识库 |
| 成本 | 每次训练成本高 | 只需更新向量库 |
工作原理
用户提问 → 向量化 → 向量数据库检索 → 获取相关知识 → LLM 生成答案
二、文本向量化
2.1 Embedding 模型
QwenEmbeddingModel embeddingModel = QwenEmbeddingModel.builder()
.apiKey(System.getenv("ALI_AI"))
.build();
Response<Embedding> embed = embeddingModel.embed("你好,我是ZHECSDN");
System.out.println(embed.content().vector().length); // 向量维度
System.out.println(embed.content()); // 向量内容
核心概念:
- Embedding:将文本转换为高维向量
- 语义相似性:语义相近的文本,向量距离更近
- 向量维度:通义千问 embedding 模型输出 1536 维向量
2.2 向量存储与检索
// 1. 创建内存向量数据库
InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
// 2. 准备文本片段并嵌入
TextSegment segment1 = TextSegment.from("预订航班规则...");
Embedding content1 = embeddingModel.embed(segment1).content();
embeddingStore.add(content1, segment1);
// 3. 向量检索
Embedding searchVector = embeddingModel.embed("退票多少钱?").content();
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(searchVector)
.maxResults(1) // 返回最相关的 1 条
.minScore(0.6) // 最小相似度阈值, 取值范围[0,1]
.build();
EmbeddingSearchResult<TextSegment> searched = embeddingStore.search(searchRequest);
searched.matches().forEach(match -> {
System.out.println(match.score()); // 相似度分数
System.out.println(match.embedded().text()); // 匹配的文本
});
三、ELP 流程详解
ELP 是 RAG 的三个核心步骤:
- Extract(提取):从文档中提取文本
- Load(加载):将文本加载到系统中
- Process(处理):分割、向量化、存储
3.1 文档加载与解析
// 声明文本解析器
TextDocumentParser textDocumentParser = new TextDocumentParser();
// 从 classpath 加载文档
Document document = ClassPathDocumentLoader.loadDocument(
"rag/terms-of-service.txt",
textDocumentParser
);
支持的文档格式:
| 模块 | 解析器 | 支持格式 |
|---|---|---|
| 核心模块 | TextDocumentParser |
txt, md, html |
| apache-pdfbox | ApachePdfBoxDocumentParser |
|
| apache-poi | ApachePoiDocumentParser |
doc, docx, xls, xlsx, ppt, pptx |
| apache-tika | ApacheTikaDocumentParser |
几乎所有文件 |
3.2 文档分割策略
为什么需要分割?
- 大文本超出模型上下文窗口限制
- 提高检索精度
- 降低计算成本
三种分割器:
// 1. 按字符分割(不推荐,可能断句)
DocumentByCharacterSplitter characterSplitter = new DocumentByCharacterSplitter(
100, // 每段最长字数
10 // 重叠字数
);
// 2. 按正则表达式分割
DocumentByRegexSplitter regexSplitter = new DocumentByRegexSplitter(
"\\n\\d+\\.", // 匹配换行 + 数字 + 点
"\n", // 分隔符
70, // 最大长度
10, // 重叠长度
new DocumentByCharacterSplitter(100, 10)
);
// 3. 按句子分割(推荐,保证语义完整)
DocumentBySentenceSplitter sentenceSplitter = new DocumentBySentenceSplitter(
100, // 最大长度
30 // 重叠长度
);
// 分割文本
List<TextSegment> segments = regexSplitter.split(document);
分割器选择经验值:
| 场景 | 分块策略 | 参考值 |
|---|---|---|
| 微博/短文本 | 句子级分割 | 100-200 |
| 学术论文 | 段落级分割 | 300-500 |
| 法律合同 | 条款级分割 | 200-400 |
| 长篇小说 | 章节级分割 | 500-1000 |
分割注意事项:
- ❌ 分块过细:破坏上下文连贯性,增加计算成本
- ❌ 分块过宽:可能超出模型限制,降低匹配度
- ✅ 首要原则:保证句子完整性!
3.3 向量化与存储
// 1. 创建 Embedding 模型
QwenEmbeddingModel embeddingModel = QwenEmbeddingModel.builder()
.apiKey(System.getenv("ALI_AI"))
.build();
// 2. 批量嵌入所有文本片段
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
// 3. 存储到向量数据库
InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
embeddingStore.addAll(embeddings, segments);
3.4 检索增强生成
// 1. 创建聊天模型
ChatModel qwenModel = QwenChatModel.builder()
.apiKey(System.getenv("ALI_AI"))
.modelName("qwen-max")
.build();
// 2. 创建内容检索器
EmbeddingStoreContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5) // 返回最相关的 5 条
.minScore(0.6) // 最小相似度
.build();
// 3. 构建 AI 助手(集成 RAG)
public interface Assistant {
String chat(@UserMessage String message);
}
Assistant assistant = AiServices.builder(Assistant.class)
.chatModel(qwenModel)
.contentRetriever(contentRetriever) // 关键:添加内容检索器
.build();
// 4. 使用 RAG 进行问答
String answer = assistant.chat("退费费用?");
System.out.println(answer);
3.5 RAG 工作流程图
用户提问:"退费费用?"
↓
1. 问题向量化
↓
2. 向量数据库检索(返回 top 5 相关文档片段)
↓
3. 将检索到的文档片段 + 用户问题一起发送给 LLM
↓
4. LLM 基于检索到的知识生成答案
↓
AI 回复:"根据服务条款,取消费用为:经济舱 75 元..."
四、Spring Boot 集成
4.1 应用启动时加载 RAG 数据
@SpringBootApplication
public class Langchain4jSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(Langchain4jSpringBootApplication.class, args);
}
@Bean
CommandLineRunner insertTermsOfServiceToVectorStore(
QwenEmbeddingModel qwenEmbeddingModel,
EmbeddingStore<TextSegment> embeddingStore) {
return args -> {
// 加载文件
Document document = ClassPathDocumentLoader.loadDocument(
"rag/terms-of-service.txt",
new TextDocumentParser()
);
// 分割文件 - 使用句子分割器
DocumentBySentenceSplitter splitter = new DocumentBySentenceSplitter(100, 20);
List<TextSegment> segments = splitter.split(document);
// 向量化并存储
List<Embedding> embeddings = qwenEmbeddingModel.embedAll(segments).content();
embeddingStore.addAll(embeddings, segments);
System.out.println("RAG 数据加载完成,共 " + segments.size() + " 个片段");
};
}
}
4.2 AiConfig 配置
@Configuration
public class AiConfig {
public interface Assistant {
String chat(@UserMessage String message);
}
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
return new InMemoryEmbeddingStore<>();
}
@Bean
public Assistant assistant(ChatModel qwenChatModel,
QwenEmbeddingModel embeddingModel,
EmbeddingStore<TextSegment> embeddingStore) {
// 创建内容检索器
EmbeddingStoreContentRetriever contentRetriever =
EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5)
.minScore(0.6)
.build();
return AiServices.builder(Assistant.class)
.chatModel(qwenChatModel)
.contentRetriever(contentRetriever)
.build();
}
}
五、向量数据库选型
| 类型 | 代表产品 | 适用场景 |
|---|---|---|
| 内存型 | InMemoryEmbeddingStore |
测试、小规模应用 |
| 云原生 | Pinecone、Weaviate、Milvus Cloud | 生产环境、大规模数据 |
| 自托管 | Milvus、Chroma、Qdrant | 数据敏感、需要私有部署 |
| 混合型 | Elasticsearch + 向量插件 | 已有 ES 集群 |
六、最佳实践
6.1 提升检索质量
-
优化分块策略
- 保证句子完整性
- 适当的重叠(10%-20%)保持上下文连贯
-
调整检索参数
EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .maxResults(5) // 根据任务复杂度调整 .minScore(0.6) // 平衡召回率和准确率 .build(); -
元数据过滤
TextSegment segment = TextSegment.from("文本内容"); segment.metadata().put("category", "航空政策"); // 检索时过滤 Filter filter = Filter.eq("category", "航空政策");
6.2 RAG 应用场景
| 场景 | 说明 | 示例 |
|---|---|---|
| 智能客服 | 基于企业知识库回答 | 航空客服、电商客服 |
| 文档问答 | 对长篇文档进行问答 | 合同审查、论文阅读 |
| 代码助手 | 基于代码库回答问题 | 内部 API 文档查询 |
| 知识管理 | 企业知识库智能检索 | 员工手册、技术规范 |
七、总结
RAG 是企业级 AI 应用的核心技术:
- ✅ 知识增强:基于私有文档回答问题
- ✅ 减少幻觉:答案来自真实文档
- ✅ 实时更新:只需更新向量库
- ✅ 向量检索:语义相似度匹配
相关笔记:
更多推荐


所有评论(0)