0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java开发者LLM实战——使用LangChain4j构建本地RAG系统

京东云 来源:jf_75140285 作者:jf_75140285 2024-07-02 10:32 次阅读

1、引言

由于目前比较火的chatGPT是预训练模型,而训练一个大模型是需要较长时间(参数越多学习时间越长,保守估计一般是几个月,不差钱的可以多用点GPU缩短这个时间),这就导致了它所学习的知识不会是最新的,最新的chatGPT-4o只能基于2023年6月之前的数据进行回答,距离目前已经快一年的时间,如果想让GPT基于近一年的时间回复问题,就需要RAG(检索增强生成)技术了。

wKgZomaDZquAZySvAALANhIlghM326.png

此外,对于公司内部的私有数据,为了数据安全、商业利益考虑,不能放到互联网上的数据,因此GPT也没有这部分的知识,如果需要GPT基于这部分私有的知识进行回答,也需要使用RAG技术。

wKgZomaDZq-AGF5DAAMJVqUI0Gw144.png

本文将通过实战代码示例,意在帮助没有大模型实战经验的Java工程师掌握使用LangChain4j框架进行大模型开发。

2、基本概念

2.1 什么是RAG

RAG(Retrieval-Augmented Generation)的核心思想是:将传统的信息检索(IR)技术与现代的生成式大模型(如chatGPT)结合起来。

具体来说,RAG模型在生成答案之前,会首先从一个大型的文档库或知识库中检索到若干条相关的文档片段。再将这些检索到的片段作为额外的上下文信息,输入到生成模型中,从而生成更为准确和信息丰富的文本。

RAG的工作原理可以分为以下几个步骤:

1.接收请求:首先,系统接收到用户的请求(例如提出一个问题)。

2.信息检索(R):系统从一个大型文档库中检索出与查询最相关的文档片段。这一步的目标是找到那些可能包含答案或相关信息的文档。

3.生成增强(A):将检索到的文档片段与原始查询一起输入到大模型(如chatGPT)中,注意使用合适的提示词,比如原始的问题是XXX,检索到的信息是YYY,给大模型的输入应该类似于:请基于YYY回答XXXX。

4.输出生成(G):大模型基于输入的查询和检索到的文档片段生成最终的文本答案,并返回给用户。

第2步骤中的信息检索,不一定必须使用向量数据库,可以是关系型数据库(如MySQL)或全文搜索引擎(如Elasticsearch, ES),

但大模型应用场景广泛使用向量数据库的原因是:在大模型RAG的应用场景中,主要是要查询相似度高的某几个文档,而不是精确的查找某一条(MySQL、ES擅长)。

相似度高的两个文档,可能不包含相同的关键词。 例如,句子1: "他很高兴。" 句子2: "他感到非常快乐。" 虽然都是描述【他】很开心快乐的心情,但是不包含相同的关键词;

包含相同的关键词的两个文档可能完全没有关联,例如:句子1: "他喜欢苹果。" 句子2: "苹果是一家大公司。" 虽然都包含相同的关键词【苹果】,但两句话的相似度很低。

2.2 LangChain4j简介

LangChain4j是LangChiain的java版本,

LangChain的Lang取自Large Language Model,代表大语言模型,

Chain是链式执行,即把语言模型应用中的各功能模块化,串联起来,形成一个完整的工作流。

它是面向大语言模型的开发框架,意在封装与LLM对接的细节,简化开发流程,提升基于LLM开发的效率。

更多介绍,详见: https://github.com/langchain4j/langchain4j/blob/main/README.md

2.3 大模型开发 vs. 传统JAVA开发

大模型开发——大模型实现业务逻辑:

开发前,开发人员关注数据准备(进行训练)、选择和微调模型(得到更好的效果,更能匹配业务预期),

开发过程中(大多数时候),重点在于如何有效的与大模型(LLM)进行沟通,利用LLM的专业知识解决特定的业务问题,

开发中更关注如何描述问题(提示工程 Propmt Engineering)进行有效的推理,关注如何将大模型的使用集成到现有的业务系统中。

传统的JAVA开发——开发者实现业务逻辑:

开发前,开发人员关注系统架构的选择(高并发、高可用),功能的拆解、模块化等设计。

开发过程中(大多数时候)是根据特定的业务问题,设计特定的算法、数据存储等以实现业务逻辑,以编码为主。

3. 实战经验

3.1 环境搭建

3.1.1 向量库(Chroma)

Windows:

先安装python,参考: https://docs.python.org/zh-cn/3/using/windows.html#the-full-installer

PS:注意需要配置环境变量

验证-执行:

python --version

wKgaomaDZrCAU7OgAAAXfU9xWxQ204.png

再安装chroma,参考:https://docs.trychroma.com/getting-started

验证-执行:

chroma run

wKgZomaDZrGAVPT8AAB6U8_1Dr4536.png

Mac:

现先安装python

brew install python

或者下载安装: https://www.python.org/downloads/macos/

验证-执行:

python --version

wKgaomaDZrKAVN8hAACFwKUj46Q886.png

安装chroma(同上),参考:https://docs.trychroma.com/getting-started

验证-执行:

chroma run

wKgZomaDZrOAZIeNAAG22JJ75Y0986.png



3.1.2 集成LangChain4j

< properties >
        < langchain4j.version >0.31.0< /langchain4j.version >
< /properties >
< dependency >
	< groupId >dev.langchain4j< /groupId >
	< artifactId >langchain4j-core< /artifactId >
	< version >${langchain4j.version}< /version >
< /dependency >
< dependency >
	< groupId >dev.langchain4j< /groupId >
	< artifactId >langchain4j< /artifactId >
	 < version >${langchain4j.version}< /version > 
< /dependency >
< dependency >
	< groupId >dev.langchain4j< /groupId >
	< artifactId >langchain4j-open-ai< /artifactId >
	 < version >${langchain4j.version}< /version > 
< /dependency >
< dependency >
	< groupId >dev.langchain4j< /groupId >
	< artifactId >langchain4j-embeddings< /artifactId >
	 < version >${langchain4j.version}< /version > 
< /dependency >
< dependency >
	< groupId >dev.langchain4j< /groupId >
	< artifactId >langchain4j-chroma< /artifactId >
	 < version >${langchain4j.version}< /version > 
< /dependency >
< dependency >
	< groupId >io.github.amikos-tech< /groupId >
	< artifactId >chromadb-java-client< /artifactId >
	 < version >${langchain4j.version}< /version > 
< /dependency >

3.2 程序编写

3.2.1 项目结构

LangChain ├── core │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── cn.jdl.tech_and_data.ka │ │ │ │ ├── ChatWithMemory │ │ │ │ ├── Constants │ │ │ │ ├── Main │ │ │ │ ├── RagChat │ │ │ │ └── Utils │ │ │ ├── resources │ │ │ │ ├── log4j2.xml │ │ │ │ └── 笑话.txt │ │ ├── test │ │ │ └── java │ ├── target ├── pom.xml ├── parent [learn.langchain.parent] ├── pom.xml



3.2.2 知识采集

一般是公司内网的知识库中或互联网上进行数据采集,获取到的文本文件、WORD文档或PDF文件,本文使用resources目录下的【笑话.txt】作为知识采集的结果文件

URL docUrl = Main.class.getClassLoader().getResource("笑话.txt");
if(docUrl==null){
    log.error("未获取到文件");
}
Document document = getDocument(docUrl);
if(document==null){
    log.error("加载文件失败");
}
private static Document getDocument(URL resource) {
    Document document = null;
    try{
        Path path = Paths.get(resource.toURI());
        document = FileSystemDocumentLoader.loadDocument(path);
    }catch (URISyntaxException e){
        log.error("加载文件发生异常", e);
    }
    return document;
}

3.2.3 文档切分

使用dev.langchain4j.data.document.splitter.DocumentSplitters#recursize

它有三个参数:分段大小(一个分段中最大包含多少个token)、重叠度(段与段之前重叠的token数)、分词器(将一段文本进行分词,得到token)

其中,重叠度的设计是为了减少按大小拆分后切断原来文本的语义,使其尽量完整。

wKgaomaDZrSAN4cuAAG9bAJR9OQ826.png

DocumentSplitter splitter = DocumentSplitters.recursive(150,10,new OpenAiTokenizer());
splitter.split(document);

关于Token(标记)

Token是经过分词后的文本单位,即将一个文本分词后得到的词、子词等的个数,具体取决于分词器(Tokenizer),

比如:我喜欢吃苹果,可以拆分成我/喜欢/吃/苹果,token数量=4, 也可以拆分成我/喜/欢/吃/苹果,token数量=5

chatGPT使用的是BPE(Byte Pair Encoding)算法进行分词,参见: https://en.wikipedia.org/wiki/Byte_pair_encoding

对于上面文本的分词结果如下:

18:17:29.371 [main] INFO  TokenizerTest - 待分词的文本:我喜欢吃苹果
18:17:30.055 [main] INFO  cn.jdl.tech_and_data.ka.Utils - 当前的模型是:gpt-4o
18:17:31.933 [main] INFO  TokenizerTest - 分词结果:我 / 喜欢 / 吃 / 苹果

关于token与字符的关系:GPT-4o的回复:

wKgZomaDZraAKm17AAQnu5woQdQ880.png

关于文档拆分的目的

由于与LLM交互的时候输入的文本对应的token长度是有限制的,输入过长的内容,LLM会无响应或直接该报错,

因此不能将所有相关的知识都作为输入给到LLM,需要将知识文档进行拆分,存储到向量库,

每次调用LLM时,先找出与提出的问题关联度最高的文档片段,作为参考的上下文输入给LLM。

入参过长,LLM报错:

wKgaomaDZreAGn0uAAEoBn5eOd8152.png

虽然根据响应,允许输入1048576个字符=1024K个字符=1M个字符,

但官网文档给的32K tokens,而一般1个中文字符对应1-2个Token,因此字符串建议不大于64K,实际使用中,为了保障性能,也是要控制输入不要过长。

如下是常见LLM给定的token输入上限:

模型名称 Token 输入上限(最大长度)
GPT-3 (davinci) 4096 tokens
GPT-3.5 (text-davinci-003) 4096 tokens
GPT-4 (8k context) 8192 tokens
GPT-4 (32k context) 32768 tokens
LLaMA (7B) 2048 tokens
LLaMA (13B) 2048 tokens
LLaMA (30B) 2048 tokens
LLaMA (65B) 2048 tokens
讯飞星火(SparkDesk) 8192 tokens
文心一言(Ernie 3.0) 4096 tokens
智源悟道(WuDao 2.0) 2048 tokens
阿里巴巴 M6 2048 tokens
华为盘古(Pangu-Alpha) 2048 tokens
言犀大模型(ChatJd) 2048 tokens

文档拆分的方案langchain4j中提供了6种:

wKgZomaDZriABvhzAAKflZsl2jk436.png

1、基于字符的:逐个字符(含空白字符)分割

2、基于行的:按照换行符(n)分割

3、基于段落的:按照连续的两个换行符(nn)分割

4、基于正则的:按照自定义正则表达式分隔

5、基于句子的(使用Apache OpenNLP,只支持英文,所以可以忽略

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2979

    浏览量

    105558
  • ChatGPT
    +关注

    关注

    29

    文章

    1578

    浏览量

    8252
  • LLM
    LLM
    +关注

    关注

    1

    文章

    308

    浏览量

    492
收藏 人收藏

    相关推荐

    利用OpenVINO和LlamaIndex工具构建多模态RAG应用

    Retrieval-Augmented Generation (RAG) 系统可以通过从知识库中过滤关键信息来优化 LLM 任务的内存占用及推理性能。归功于文本解析、索引和检索等成熟工具的应用,为
    的头像 发表于 02-21 10:18 1558次阅读
    利用OpenVINO和LlamaIndex工具<b class='flag-5'>构建</b>多模态<b class='flag-5'>RAG</b>应用

    【「基于大模型的RAG应用开发与优化」阅读体验】RAG基本概念

    随着大模型在25年初的进一步发展,RAG应用已成为新的一个趋势,很荣幸有机会试读这本<基于大模型的RAG应用开发与优化>,书本很厚,有500多页,诚意满满。 本书所阐述
    发表于 02-08 00:22

    【「基于大模型的RAG应用开发与优化」阅读体验】+第一章初体验

    3降低幻觉风险:通过引入权威数据源(如学术论文、企业文档),RAG为生成过程提供“事实锚点”,减少模型虚构内容的可能性。 4轻量化部署:开发者无需频繁微调大模型,仅需优化检索模块即可提升系统
    发表于 02-07 10:42

    开发者的开源鸿蒙故事

    近日,在以“一切为了开发者”为主题的“2024开放原子开发者大会暨首届开源技术学术大会”上,开源鸿蒙5.0 Release版本正式发布,备受各方关注。该版本在系统完备度、分布式创新、开发者
    的头像 发表于 01-06 10:28 257次阅读

    《HarmonyOS第一课》焕新升级,赋能开发者快速掌握鸿蒙应用开发

    注重理论与实践的结合,提供让开发者快速上手的codelab编程练习,开发者能在实战中巩固所学,系统掌握核心开发技能。完成课程后,
    发表于 01-02 14:24

    RAG的概念及工作原理

    检索增强型生成(RAG系统正在重塑我们处理AI驱动信息的方式。作为架构师,我们需要理解这些系统的基本原理,从而有效地发挥它们的潜力。 什么是RAG? 总体而言,
    的头像 发表于 12-17 13:41 755次阅读
    <b class='flag-5'>RAG</b>的概念及工作原理

    SSM框架在Java开发中的应用 如何使用SSM进行web开发

    (full-stack)的应用程序框架,它提供了全面的基础设施建设支持,能够帮助开发者构建出企业级的应用程序。Spring的核心是控制反转(I
    的头像 发表于 12-16 17:28 767次阅读

    使用OpenVINO和LlamaIndex构建Agentic-RAG系统

    RAG 系统的全称是 Retrieval-augmented Generation,本质上是 Prompt Engineering,通过在 Prompt 中注入检索得到的外部数据,可以有效地
    的头像 发表于 10-12 09:59 405次阅读
    使用OpenVINO和LlamaIndex<b class='flag-5'>构建</b>Agentic-<b class='flag-5'>RAG</b><b class='flag-5'>系统</b>

    KaihongOS 4.1.2开发者预览版正式上线,诚邀开发者免费试用!

    独特的抢先体验机会,涵盖了原生应用开发、分布式能力、原子化服务等核心功能特性,助力开发者探索国产操作系统的更多可能性。此次发布的预览版适配RK3568、RK358
    的头像 发表于 09-28 08:07 450次阅读
    KaihongOS 4.1.2<b class='flag-5'>开发者</b>预览版正式上线,诚邀<b class='flag-5'>开发者</b>免费试用!

    OpenVINO™ C++ 在哪吒开发板上推理 Transformer 模型|开发者实战

    使用OpenVINO定制你的AI助手丨开发者实战作者:王国强苏州嘉树医疗科技有限公司算法工程师指导:颜国进英特尔边缘计算创新大使研扬科技针对边缘AI行业开发者推出的『哪吒』(Nezha)开发
    的头像 发表于 09-28 08:01 518次阅读
    OpenVINO™ C++ 在哪吒<b class='flag-5'>开发</b>板上推理 Transformer 模型|<b class='flag-5'>开发者</b><b class='flag-5'>实战</b>

    KaihongOS 4.1.2开发者预览版正式上线,诚邀开发者免费试用!

    开发者提供了独特的抢先体验机会,涵盖了原生应用开发、分布式能力、原子化服务等核心功能特性,助力开发者探索国产操作系统的更多可能性。 此次发布的预览版适配RK3568、RK3588、ES
    的头像 发表于 09-26 15:59 549次阅读

    LangChain框架关键组件的使用方法

    LangChain开发者可以轻松构建基于RAG或者Agent流水线的复杂应用体系,而目前我们已经可以在LangChain的关键组件
    的头像 发表于 08-30 16:55 759次阅读
    <b class='flag-5'>LangChain</b>框架关键组件的使用方法

    英特尔开发套件『哪吒』在Java环境实现ADAS道路识别演示 | 开发者实战

    本文使用来自OpenModelZoo的预训练的road-segmentation-adas-0001模型。ADAS代表高级驾驶辅助服务。该模型识别四个类别:背景、道路、路缘和标记。硬件环境此文使用了英特尔开发套件家族里的『哪吒』(Nezha)开发板,其为研扬科技针对边缘A
    的头像 发表于 04-29 08:07 755次阅读
    英特尔<b class='flag-5'>开发</b>套件『哪吒』在<b class='flag-5'>Java</b>环境实现ADAS道路识别演示 | <b class='flag-5'>开发者</b><b class='flag-5'>实战</b>

    使用Redis和Spring Ai构建rag应用程序

    随着AI技术的不断进步,开发者面临着如何有效利用现有工具和技术来加速开发过程的挑战。Redis与SpringAI的结合为Java开发者提供了一个强大的平台,以便快速
    的头像 发表于 04-29 08:04 1248次阅读
    使用Redis和Spring Ai<b class='flag-5'>构建</b><b class='flag-5'>rag</b>应用程序

    【转载】英特尔开发套件“哪吒”快速部署YoloV8 on Java | 开发者实战

    部署到生产系统中。通过简化的开发工作流程,OpenVINO可赋能开发者在现实世界中部署高性能应用程序和算法。 今天我们将基于哪吒开发者套件平台来快速部署OpenVI
    的头像 发表于 03-23 08:05 740次阅读
    【转载】英特尔<b class='flag-5'>开发</b>套件“哪吒”快速部署YoloV8 on <b class='flag-5'>Java</b> | <b class='flag-5'>开发者</b><b class='flag-5'>实战</b>