大模型的知识来自受训练的数据,具有一定的局限性。 如果想让大模型了解特定领域的知识或专有数据,可以使用RAG或者数据微调的方式。
RAG介绍
RAG (Retrieval-Augmented Generation),内容检索增强生成。通过RAG我们可以构建专有领域的知识库,在向大模型发送问题之前,可以先通过RAG检索相应的内容,然后将我们的问题和检索到的内容一起发给大模型,大模型根据我们给的内容进行回答,可以使回答的内容更准确。
RAG 过程分为 2 个不同的阶段:索引和检索。
索引阶段:
在索引阶段,对文档进行预处理。简单来说,会对文档进行分块,并对分块的数据进行嵌入存储(数据存入向量数据库中)。
其流程大致如下:

该流程图来自LangChain4j的官网
对文档进行分块,借助嵌入模型(Embeding Model)对分块数据进行向量化处理,然后将分块和向量化后的数据存入向量数据库中。
检索阶段
向大模型提问时,通过嵌入模型对问题进行向量化处理,并通过相似度分析,获取与问题相似的分段信息,然后将分段和问题作为提示词,一起发送给大模型进行处理。
其流程大致如下:

该流程图来自LangChain4j的官网
Easy RAG
LangChain4j中提供了3中风格的实现:
- Easy RAG
- Naive RAG
- Advanced RAG
Easy RAG是LangChain4j中提供的针对RAG的一种简单实现方式,对外隐藏了很多实现细节。
导入jar
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-easy-rag</artifactId>
<version>1.0.0-beta2</version>
</dependency>
准备一个文档

注意:文档放在resources目录下
测试代码
package com.renr.langchain4jnew.app4;
import com.renr.langchain4jnew.constant.CommonConstants;
import dev.langchain4j.community.model.zhipu.ZhipuAiChatModel;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import lombok.extern.slf4j.Slf4j;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import java.util.Scanner;
@Slf4j
public class EasyRAG {
public static void main(String[] args) throws URISyntaxException {
ChatLanguageModel model = ZhipuAiChatModel.builder()
// 模型key
.apiKey(CommonConstants.API_KEY)
// 精确度
.temperature(0.9)
.model("GLM-4-Flash")
.maxRetries(3)
.callTimeout(Duration.ofSeconds(60))
.connectTimeout(Duration.ofSeconds(60))
.writeTimeout(Duration.ofSeconds(60))
.readTimeout(Duration.ofSeconds(60))
.logRequests(true)
.logResponses(true)
.build();
// 获取待加载的文档路径
URL fileUrl = EasyRAG.class.getClassLoader().getResource("document/a.txt");
Path path = Paths.get(fileUrl.toURI());
// 加载文档数据
Document documents = FileSystemDocumentLoader.loadDocument(path);
// 向量数据存储在内存中
InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
// 将文档存储到指定的“向量存储对象”中
EmbeddingStoreIngestor.ingest(documents, embeddingStore);
// 返回内容检索对象
ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.from(embeddingStore);
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
// 指定内容检索对象
.contentRetriever(contentRetriever)
.build();
String answer = assistant.chat("河南省直第三人民医院的地址");
System.out.println(answer);
}
}
不启用RAG的执行情况
我们先注释掉contentRetriever(contentRetriever):
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(CHAT_MODEL)
// .contentRetriever(contentRetriever)
.build();
发送请求数据如下:
18:59:15.336 [main] DEBUG dev.langchain4j.community.model.zhipu.RequestLoggingInterceptor - Request:
- method: POST
- url: https://open.bigmodel.cn/api/paas/v4/chat/completions
- headers: [Authorization: Bearer ey...fQ.ew0KICAiZXhwIiA6IDE3NDQ4ODkzNTUyNjksDQogICJhcGlfa2V5IiA6ICJkMjMzNGIyZTk4NTE0YWUwOTIzMDQ4YTM4NDEzNTMwNiIsDQogICJ0aW1lc3RhbXAiIDogMTc0NDg4NzU1NTI2OQ0KfQ.PwhX7_zca8YRl0XSfiu_ASRBC-ifMhz6udigGY4pOAc]
- body: {
"model" : "GLM-4-Flash",
"messages" : [ {
"role" : "user",
"content" : "河南省直第三人民医院的地址"
} ],
"stream" : false,
"temperature" : 0.9,
"max_tokens" : 512,
"tool_choice" : "auto"
}
执行结果如下:

启用RAG的执行情况
取消上述代码注释,启用检索增强,发送的请求如下:
18:36:34.497 [main] DEBUG dev.langchain4j.community.model.zhipu.RequestLoggingInterceptor - Request:
- method: POST
- url: https://open.bigmodel.cn/api/paas/v4/chat/completions
- headers: [Authorization: Bearer ey...fQ.ew0KICAiZXhwIiA6IDE3NDQ4ODc5OTQ0MjksDQogICJhcGlfa2V5IiA6ICJkMjMzNGIyZTk4NTE0YWUwOTIzMDQ4YTM4NDEzNTMwNiIsDQogICJ0aW1lc3RhbXAiIDogMTc0NDg4NjE5NDQyOQ0KfQ.XX5DZAh3qINeAO-PLBSe0aGPnveBzJOSwUaYDS_FGTk]
- body: {
"model" : "GLM-4-Flash",
"messages" : [ {
"role" : "user",
"content" : "河南省直第三人民医院的地址\n\nAnswer using the following information:\n河南省直第三人民医院简介\r\n(修订日期 2025年3月)\n\n河南省直第三人民医院简介\n(修订日期 2025年3月)\n河南省直第三人民医院是河南省卫健委直属的一家“医教研转工作统筹推进、防治康养手段综合应用、吃动睡想行为全面科学”的省三级公立综合医院。是河南省干部保健定点医院。\n医院位于河南省省会郑州,有三个院区,郑东院区(郑东新区人民医院)比邻河南省政府。西院区位于中原区伏牛路陇海路交叉口;857院区位于中原区陇海路328号。医院有2个急救站,5个急救联盟单位、4个社区卫生服务中心;下设司法鉴定中心。\n\n成立了“河南省慈善联合总会.道健基金”,开展公益行动,救助贫困患者及资助诊断不明、疗效不佳、复杂病例的手术患者享受国内知名医院专家手术。"
} ],
"stream" : false,
"temperature" : 0.9,
"max_tokens" : 512,
"tool_choice" : "auto"
}
执行结果如下:

从两次执行结果看,启用RAG后,提示词中增加了从文档中检索的内容,并且和原来的问题一起发送给了大模型,大模型根据提示词内容,返回了文档中给出的医院的准确地址数据。
而没有启用RAG时,大模型给出的结果明显和文档中的结果不符。
注意:Easy RAG只是为了体验下RAG的作用,由于内部隐藏了很多实现细节,灵活性差,实际使用效果有限。比如,如果我们询问大模型:河南省直第三人民医院有多少职工,RAG并不能检索出有效的数据,大模型也无法返回准确的信息。
859

被折叠的 条评论
为什么被折叠?



