当前位置: 首页 > ops >正文

【LangChain4J】LangChain4J 第四弹:RAG 的多种实现方式

目录

一、RAG 的定义

二、简单 RAG 的实现

三、高级 RAG 实现


一、RAG 的定义

定义:RAG(Retrieval-Augmented Generation,检索增强生成)是通过从外接数据源检索相关信息,并注入提示词,提升大语言模型(LLM)查询精准度的一种技术。

通过这种实现方式,大语言模型可以获取到特定领域的相关信息,并能够利用这些信息进行回复,从而降低了发生幻觉的可能性。

RAG 解决传统大模型局限性

  • 知识过时:传统大模型依赖预训练数据,无法获取最新信息。

  • 幻觉问题:传统模型可能生成不准确或虚假的信息。

RAG 优势

  • 实时更新:允许模型访问最新信息,解决知识局限性问题。

  • 提高准确性:通过引用外部知识库,减少幻觉现象。

  • 经济高效:与重新训练模型相比,降低了更新成本。

二、简单 RAG 的实现

1. 添加依赖

<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-easy-rag</artifactId><version>1.0.0-beta3</version>
</dependency>

2. 加载知识库

将知识库加载到集合中(EmbeddingStoreIngestor 内置嵌入模型实现数据转换向量,但是维度是固定的,精确度不会特别高):

    // 加载知识库Document document = FileSystemDocumentLoader.loadDocument("D:\\forum_system.sql");// 向量存储器:负责将向量存储到向量数据库EmbeddingStoreIngestor.ingest(document,embeddingStore);

3. 知识库存入向量数据库

    Document document = FileSystemDocumentLoader.loadDocument("D:\\forum_system.sql");// 向量存储器:负责将向量存储到向量数据库EmbeddingStoreIngestor.ingest(document,embeddingStore);

实现过程:LangChain4j 选择 bge-small-en-v1.5 作为 Easy RAG 的默认嵌入模型,通过 SPI(服务发现机制)加载实例,并使用分词器将其文本分块,并存储向量数据库中。

4. 调用知识库查询信息

// 首先将知识库加载到数据库中@PostConstructpublic void init() {Document document = FileSystemDocumentLoader.loadDocument("D:\\forum_system.sql");// 向量存储器:负责将向量存储到向量数据库EmbeddingStoreIngestor.ingest(document,embeddingStore);}@RequestMapping("/chat")public String query(String question) {EasyRagService easyRagService = AiServices.builder(EasyRagService.class).chatLanguageModel(qwenChatModel)// 关键代码.contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore)).build();return easyRagService.chat(question);}

三、高级 RAG 实现

它的执行流程如下:

  1. 用户执行一个[查询]操作,该查询被转换为 UserMessage 对象。

  2. QueryTransformer 将[查询]转换成一个或多个 Query 对象。

  3. 每个 Query 对象通过 QueryRouter 被路由到一个或多个 ContentRetriever。

  4. 每个 ContentRetriever 为每个 Query 检索相关的 Content 内容。

  5. ContentAggregator(内容聚合器)将所有检索到的 Content 合并成一个最终的排序列表。

  6. 这个 Content 列表被注入到原始的 UserMessage 中。

  7. 最终,包含原始查询和相关内容的 UserMessage 被发送给大语言模型(LLM)。

/*** 1.索引阶段:将知识库保存到 Milvus*/@PostConstructpublic void init() {createDocumentStore("D:\\data\sanguo.md",qwenEmbeddingModel,sanguoEmbeddingStore);createDocumentStore("D:\\data\\pig.md",qwenEmbeddingModel,pigEmbeddingStore);}private void createDocumentStore(String path, EmbeddingModel qwenEmbeddingModel, EmbeddingStore<TextSegment> pigEmbeddingStore) {//1.文本加载器(文本解析器)Document document = FileSystemDocumentLoader.loadDocument(path);//2.文本转换(数据清除)DocumentTransformer transformer = doc ->{return Document.from(doc.text().replace("#",""),doc.metadata());};document = transformer.transform(document);//3.文本分词器DocumentSplitter documentSplitter = DocumentSplitters.recursive(300,30,new HuggingFaceTokenizer());List<TextSegment> segmentList = documentSplitter.split(document);//4.文本向量化List<Embedding> embeddingList = qwenEmbeddingModel.embedAll(segmentList).content();//5.数据存储到向量数据库sanguoEmbeddingStore.addAll(embeddingList,segmentList);}@RequestMapping("/chat")public String query(String question) {//1.创建上下文对象:两个 三国检索器ContentRetriever sanguoContentRetriever = EmbeddingStoreContentRetriever.builder().embeddingModel(qwenEmbeddingModel).embeddingStore(sanguoEmbeddingStore).maxResults(1).minScore(0.7).build();// 老母猪检索器ContentRetriever pigContentRetriever = EmbeddingStoreContentRetriever.builder().embeddingModel(qwenEmbeddingModel).embeddingStore(pigEmbeddingStore).maxResults(1).minScore(0.7).build();// 构建查询路由Map<ContentRetriever,String> map = new HashMap<>();map.put(sanguoContentRetriever,"三国");map.put(pigContentRetriever,"老母猪");QueryRouter queryRouter = new LanguageModelQueryRouter(qwenChatModel,map);// 检索增强器RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder().queryRouter(queryRouter).build();// 实例化 AiServiceRagService ragService = AiServices.builder(RagService.class).chatLanguageModel(qwenChatModel).retrievalAugmentor(retrievalAugmentor).build();return ragService.query(question);}interface RagService{String query(String question);}
http://www.xdnf.cn/news/12825.html

相关文章:

  • 《汇编语言》第16章 直接定址表——实验16 编写包含多个功能子程序的中断例程
  • 【时时三省】(C语言基础)局部变量和全局变量例题
  • 贝叶斯定理与医学分析(t检验场景)
  • 【量化】策略交易 - 均线策略(Moving Average Strategy)
  • 如何在Redhat Linux7.9下安装配置MySQL
  • 历史数据分析——辽港股份
  • Java高频面试之并发编程-24
  • Semantic-SAM: Segment and Recognize Anything at Any Granularity
  • 大模型如何选型?嵌入模型如何选型?
  • 【PhysUnits】17.2 配套变量结构体 Var(variable.rs)
  • 一套个人知识储备库构建方案
  • UE的AI行为树Selector和Sequence如何理解
  • 数据结构——D/串
  • comfyui 工作流中 图生视频 如何增加视频的长度到5秒
  • C++ - string 的使用 #auto #范围for #访问及遍历操作 #容量操作 #修改操作 #其他操作 #非成员函数
  • Vivado软件开发流程操作详解
  • 五年级数学知识边界总结思考-下册
  • 【会员专享数据】1980—2022年中国逐日月年潜在蒸散发栅格数据
  • JavaScript 数组学习总结
  • Spyglass:跨时钟域同步(时钟门控单元)
  • eBPF系列--BCC中提供的BPF maps高级抽象如何映射到内核的BPF maps?
  • 【Ragflow】27.RagflowPlus(v0.4.1):小版本迭代,问题修复与功能优化
  • 比较一组结构之间的变换
  • Python爬虫实战:研究PySocks库相关技术
  • Halcon案例(三):C#联合Halcon识别排线
  • 【整数逐位除法求余补〇完整版】2022-4-11
  • 1 Studying《Linux Media Documentation》
  • 深度学习模块缝合
  • 【redis】线程IO模型
  • 第16届蓝桥杯青少Stema11月 Scratch编程——初/中级组真题——行走的图形