RAG(检索增强生成)主要解决大模型的两大痛点:
- 知识截止时间问题:大模型的训练数据存在时间截止,无法获知最新资料。
- 幻觉问题:模型可能编造出并不存在的答案。
核心思想:不把全部文档一次性塞给大模型,而是在用户提问时,先从私有知识库中检索出相关片段,再将检索到的片段与用户问题一并交给大模型,让模型参考检索到的真实资料进行回答。
一、快速入门
引入依赖
html
<!--rag-easy依赖-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-easy-rag</artifactId>
<version>1.0.1-beta6</version>
</dependency>
2.构建向量数据库操作对象
CommonConfig.java
java
//构建向量数据库操作对象
@Bean
public EmbeddingStore store(){
//embeddingStore的对象, 这个对象的名字不能重复,所以这里使用store
//1.加载文档进内存
//List<Document> documents = ClassPathDocumentLoader.loadDocuments("content");
List<Document> documents = ClassPathDocumentLoader.loadDocuments("content",new ApachePdfBoxDocumentParser());
//2.构建文档分割器对象
DocumentSplitter ds = DocumentSplitters.recursive(500,100);
//3.构建一个EmbeddingStoreIngestor对象,完成文本数据切割,向量化, 存储
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
//.embeddingStore(store)
.embeddingStore(redisEmbeddingStore)
.documentSplitter(ds)
.embeddingModel(embeddingModel)
.build();
ingestor.ingest(documents);
return redisEmbeddingStore;
}
① 文档加载(DocumentLoader)
java
List<Document> documents = ClassPathDocumentLoader.loadDocuments
("content",new ApachePdfBoxDocumentParser());
ClassPathDocumentLoader:读取resources 下 classpath 资源目录 ;目录名content,存放 pdf 知识库文件。ApachePdfBoxDocumentParser():PDF 解析器,专门解析 PDF 文件提取文本。
② 文档分割器 DocumentSplitter(切片 Chunk)
java
DocumentSplitter ds = DocumentSplitters.recursive(500,100);
recursive(500,100):递归分割器500:每块最大字符数(chunkSize = 500)100:重叠字符(overlap =100),相邻两块重复 100 字符,防止语义被切断。
③ EmbeddingStoreIngestor 数据摄取器(核心对象)
java
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
.embeddingStore(redisEmbeddingStore) //向量存储:Redis向量库
.documentSplitter(ds) //文档切片规则
.embeddingModel(embeddingModel) //Embedding嵌入模型(向量化)
.build();
EmbeddingStoreIngestor 是 LangChain4j 提供的工具,一站式完成三件工作:
- 接收原始
Document文档 - 使用
documentSplitter执行文本分块(chunk) - 调用
embeddingModel对每一个 chunk 生成向量 - 将「文本片段 + 向量 + 元数据」保存进
embeddingStore向量数据库
④ ingest () 执行入库
java
ingestor.ingest(documents);
调用ingest()方法,触发离线入库流程;程序启动的时候就会执行文档加载、切片、向量化存入 Redis 向量库。
⑤ 返回 Bean
return redisEmbeddingStore;
把 Redis 向量存储对象注册为 Spring Bean,后面检索阶段Retriever就可以直接注入使用。
3.构建向量数据库检索对象
java
//构建向量数据库检索对象
@Bean
public ContentRetriever contentRetriever(/*EmbeddingStore store*/){
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(redisEmbeddingStore) //指定用Redis向量库
//可以查出来的分数。分数范围0~1,越靠近1语义越相似
.minScore(0.5)
//最大查出来的向量数量
.maxResults(3)
//传入Embedding模型,生成问题向量做相似度比对
.embeddingModel(embeddingModel)
.build();
二、核心API
1.DocumentLoader文档加载器
①FileSystemDocumentLoader磁盘绝对路径(服务器磁盘、本机 C 盘 / D 盘)
java
List<Document> documents = FileSystemDocumentLoader.loadDocuments
("C:\\Users\\Administrator\\ideaProjects\\consultant\\src\\main\\resources\\content");
②ClassPathDocumentLoader类路径加载(主用)
③UrlDocumentLoader网络 URL 加载器
2.DocumentParser文档解析器
①TextDocumentParser 专门解析纯文本文件(.txt)。只适合 txt,不能解析 pdf、office。
②ApachePdfBoxDocumentParser 解析PDF 文件。适合知识库里面大量 PDF 文档的场景。
java
List<Document> documents = ClassPathDocumentLoader.loadDocuments
("content",new ApachePdfBoxDocumentParser());
3.DocumentSplitter段落解析器
DocumentSplitters.recursive (...) 【默认递归分割器】
递归分层切割策略:先段落分割,再行,再句子分割
java
//构建文档分割器对象
//片段最大容量字符500,两个片段最多重复字符100
DocumentSplitter ds = DocumentSplitters.recursive(500,100);
java
//3.构建一个EmbeddingStoreIngestor对象,完成文本数据切割,向量化, 存储
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
//.embeddingStore(store)
.embeddingStore(redisEmbeddingStore)
.documentSplitter(ds)//!!段落分割器
.embeddingModel(embeddingModel)
.build();

4.EmbeddingModel 向量模型
application.yml
bash
langchain4j:
open-ai:
embedding-model:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${API-KEY}
model-name: text-embedding-v3
log-requests: true
log-responses: true
1、EmbeddingStoreIngestor向量存储
java
//3.构建一个EmbeddingStoreIngestor对象,完成文本数据切割,向量化, 存储
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
//.embeddingStore(store)//向量存储
.embeddingStore(redisEmbeddingStore)
.documentSplitter(ds)//文档分割器
.embeddingModel(embeddingModel)//注入模型
.build();
ingestor.ingest(documents);
加载文档 →切分分片 →调用 embeddingModel 做向量化 →保存进 EmbeddingStore 向量存储。
2、EmbeddingStoreContentRetriever向量检索
java
//构建向量数据库检索对象
@Bean
public ContentRetriever contentRetriever(/*EmbeddingStore store*/){
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(redisEmbeddingStore)
.minScore(0.5)//相似度最低阈值,低于0.直接过滤掉,不要这条结果
.maxResults(3)//最多返回3条匹配的分片
.embeddingModel(embeddingModel)//注入模型
.build();
用户提问的时候,先拿embeddingModel 把用户问题文本转为向量;再去向量库做相似度查询
5.EmbeddingStore 向量存储
专门操作向量数据库,完成向量数据添加保存、相似度检索。
部署 Redis‑Vector 步骤
启动容器 (docker)
bash
docker stop redis #停止旧redis容器
docker rm redis #删除旧容器
docker run --name redis-vector -d -p 6379:6379 redislabs/redissearch
- Maven 引入 starter 依赖
html
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-redis-spring-boot-starter</artifactId>
<version>1.0.1-beta6</version>
</dependency>
- application.yml 配置连接信息
vbnet
langchain4j:
community:
redis:
host: localhost
port: 6379
SpringBoot 自动装配,直接得到RedisEmbeddingStore对象。
- 业务代码中使用,分别给 Ingestor、Retriever 传入 store 对象
① EmbeddingStoreIngestor离线知识库注入
java
EmbeddingStoreIngestor.builder()
.embeddingStore(store) //向量存储
.documentSplitter(documentSplitter) //文档分割器
.embeddingModel(embeddingModel) //向量模型
.build();
文档切分完、生成向量以后,请把生成的向量 + 原文片段保存到 Redis 向量库里面。
② EmbeddingStoreContentRetriever 检索器,在线问答召回
java
return EmbeddingStoreContentRetriever.builder()
.embeddingStore(redisEmbeddingStore)//从redis里面检索召回内容
.minScore(0.5)
.maxResults(3)
.embeddingModel(embeddingModel)
.build();
用户问题做完向量化之后,请去 Redis 向量库里做相似度检索,把相关片段查回来。