使用Quarkus和LangChain4j,LLM在Java中可以实现哪些功能? 原创

发布于 2024-5-14 09:52
浏览
0收藏

本文试图通过一个有趣的原创项目,利用Quarkus和LangChain4j来揭开LLM在Java中使用的神秘面纱。

自从2022年11月公开发布以来,ChatGPT吸引了大量用户,这种人工智能模型不仅提高了他们的创造力,也激发了技术爱好者对其可能存在的缺点甚至弱点的关注。

ChatGPT以及类似的聊天机器人是被称为大型语言模型(LLM)的一种特殊类型的软件,它极大地改变了自然语言处理(NLP)领域,以提供更新和不太常见的任务,例如问答、文本生成和摘要等。所有这些术语听起来非常复杂,虽然很多文章致力阐明LLM的巨大飞跃,但本文试图了解LLM的工作原理,特别是如何在Java中使用它们,突出LLM引人注目的可能性以及存在的一些潜在问题。

LLM发展历史

自然语言处理(NLP)指的是构建能够识别、理解和生成人类语言文本的机器。对于许多人来说,这听起来像是一种新技术,但实际上它与计算机诞生在同一时期。在信息时代初期,能够自动将一种人类语言翻译成另一种语言是程序员的梦想。

艾伦·图灵在1950年发表的一篇论文中指出,如果一台机器能产生与人类无法区别的响应,那么它就可以被认为是“智能机器”。这种被称为图灵测试的方法,现在被认为是所谓的机器“智能”的一种不完整案例,因为它很容易被现代程序实现,这些程序是为了模仿人类的语言而设计的。

世界上首个NLP程序采用了一种简单的方法,使用一组规则和启发式来模仿会话。1966年,麻省理工学院(MIT)教授Joseph Weizenbaum发布了历史上第一个聊天机器人Eliza。基于通用语言模式匹配,该程序通过提出开放式的问题,并对它不“理解”的句子给出通用的回答,例如“请继续”,创造了一种与人会话的假象。

在接下来的几十年,基于规则的文本解析和模式匹配仍然是最常见的NLP方法。到20世纪90年代,NLP发生了一个重要的范式转变,包括采用统计方法取代基于规则的方法。与试图定义和构建语法的原有模型不同,新模型旨在通过“训练”来“学习”语言模式。现在,大量文档被用来为NLP程序提供数据,以便“教授”它们一个给定的语言模型。因此,人们开始为文本生成、分类或其他自然语言任务“训练”程序,一开始,这个过程是基于输入序列的,模型将这些输入序列分解为令牌,通常是单词或部分单词,然后再转换为训练算法给出的相关数学表示。最后,将这种特殊的表示形式转换回令牌,以生成可读的结果。这种来回的令牌化过程称为“编码-解码”。

NLP研究人员在2014年发现了另一种替代传统方法,即通过编码器-解码器模型逐条传递序列。这一新方法引起了人们的注意,它包括让解码器搜索完整的输入序列,并试图从语言模型的角度找到最相关的的部分。几年后,谷歌公司发表了一篇题为《注意力就是你所需要的一切》的论文。其研究结果表明,基于这种新的注意力原理的模型速度更快,并且可以并行化,它们被称为Transformers。

Transformers标志着LLM的诞生,因为它们使得训练更大数据集的模型成为可能。2018年,OpenAI公司推出了第一个名为生成式预训练Transformers (GPT)的LLM。这个LLM是一个基于Transformers的LLM,它使用大量未标记的数据进行训练,然后根据特定任务进行微调,例如机器翻译、文本分类、情感分析等。而在这一年,谷歌公司推出了另一个LLM ——BERT (基于Transformers的双向编码器表示),它使用了更大的训练数据量,包括数十亿个单词和1亿多个参数。

与以前的NLP程序不同,这些LLM并不针对特定任务。与其相反,它们只是被训练来预测最适合给定模型特定场景的令牌。它们被应用于不同的领域,并正在成为人们日常生活中不可或缺的一部分。例如苹果的Siri、亚马逊的Alexa或Google Home这些会话代理能够倾听用户的询问,将声音转化为文本,然后回答问题。它们的通用目的和多功能性导致了广泛的自然语言任务,包括但不限于:

  • 语言建模
  • 回答问题
  • 编码
  • 内容生成
  • 逻辑推理
  • 等等。

会话LLM

LLM的任务在于他们能够以高度灵活的方式为各种情况生成文本,这使他们能够完美地与人类交谈。聊天机器人是专门为会话使用而设计的LLM。ChatGPT是最著名的LLM,但还有很多其他的LLM,例如:

  • 谷歌的Bard
  • 微软的Bing AI
  • Meta的LLaMa
  • Anthropic的Claude
  • GitHub的Copilot
  • 等等。

会话LLM嵌入到企业级应用程序中,是客户服务、教育、医疗保健、网络内容生成、化学、生物学等许多领域的理想解决方案。聊天机器人和虚拟助理可以通过访问会话LLM功能来提供动力。LLM在传统应用程序中的这种集成要求它们公开一致的API。为了从应用程序中调用这些API,需要提供一个工具包,它能够与人工智能模型交互并促进自定义创建。

LLM工具包

自从ChatGPT问世以来,人工智能领域得以快速发展,在所有这些新工具中,LLM工具包出现了真正的爆炸式增长。其中一些著名的LLM(例如AutoGPT、MetaGPT、AgentGPT等)试图赶上潮流。但毫无疑问,最现代也是讨论最多的是LangChain。LangChain于2022年作为开源库推出,支持Python、JavaScript和TypeScript,最初由Harrison Chase公司开发,在发布之后不久,就成为人工智能领域发展最快的项目之一。

尽管越来越受欢迎,但LangChain有一个主要缺点:缺乏Java支持。因此,为了解决这个缺点,LangChain4j在2023年初出现,作为LangChain Python库的Java实现。在以下的演示中将使用LangChain4J实现企业级Java服务和组件,这些服务和组件由最主流和最有影响力的LLM提供支持的企业级Java服务和组件。

演示项目

为了说明其论述,将使用一个简单的Java程序来执行自然语言任务。为此选择的用例是实现一个能够编写俳句的人工智能服务。《大英百科全书》对于俳句的定义是:俳句是一种不押韵的诗歌形式,由17个音节组成,分别排成5、7和5个音节的三行句子。

正如人们所看到的,这样一个任务的有用性并不真正引人注目,事实上,它不仅仅是一个真正的用例,而是一个展示LangChain4j一些功能的借口,同时使用一个有趣的并且是原创的形式。

因此,这个项目是一个专业的多模块项目,具有以下结构:

  • 一个名为llm-java的主要POM
  • 一个名为haiku的JAX-RS模块,公开调用LLM模型的REST API
  • 一个名为infra的基础设施模块,用于创建所需的Docker容器

主要POM

这个项目是Quarkus项目。因此,物料清单(BOM)的使用如下:

XML 
1  <dependencyManagement>
2    <dependencies>
3      <dependency>
4        <groupId>io.quarkus</groupId>
5        <artifactId>quarkus-bom</artifactId>
6        <version>${quarkus.version}</version>
7        <type>pom</type>
8        <scope>import</scope>
9      </dependency>
10    </dependencies>
11  </dependencyManagement>

它使用Quarkus 3.8.3、Java 17和LangChain4j 0.25.0。

JAX-RS模块

这个名为haiku的模块使用Quarkus - restasy -reactive-jackson Quarkus扩展来公开REST AP:

Java 
1 @Path("/haiku")
2 public class HaikuResource
3 {
4  private final HaikuService haikuService;
5
6  public HaikuResource(HaikuService haikuService)
7  {
8    this.haikuService = haikuService;
9  }
10
11  @GET
12  public String makeHaiku(@DefaultValue("samurai") @RestQuery String subject)
13  {
14    return haikuService.writeHaiku(subject);
15  }
16 }

这个API定义了一个监听GET HTTP请求的端点,接受俳句主题作为查询参数,该参数包含默认值:“samurai”。该模块还使用Quarkus -container-image-jib Quarkus扩展来创建运行人工智能服务的Docker映像。这个Docker镜像的属性在应用程序中定义。应用属性(application.properties)文件如下所示:

Properties files 
1 ...
2 quarkus.container-image.build=true
3 quarkus.container-image.group=quarkus-llm
4 quarkus.container-image.name=haiku
5quarkus.jib.jvm-entrypoint=/opt/jboss/container/java/run/run-java.sh
6 ...

这些属性说明新创建的Docker映像名称为quarkus-llm/haiku,其入口点将是位于容器的/opt/jboss/container/java/run目录下的run-java.sh shell脚本。

这个项目使用Quarkus扩展quarkus-langchain4j-ollama,它提供了与LangChain4j库和Ollama工具的集成。Ollama是一款先进的人工智能精简实用程序,允许用户在本地设置和运行大型LLM,例如OpenAI、Llama2、Mistral等。在这里是本地运行Llama2。这需要在应用程序中再次配置。应用属性(application.properties)采用以下语句:

Properties files 
1 quarkus.langchain4j.ollama.chat-model.model-id=llama2:latest

在此需要声明的是,为了服务人工智能请求,此处使用的LLM将是其最后版本的Llama2。现在看看人工智能服务本身:

Java 
1 @RegisterAiService
2 public interface HaikuService
3 {
4  @SystemMessage("You are a professional haiku poet")
5  @UserMessage("Write a haiku about {subject}.")
6  String writeHaiku(String subject);
7 }

可以看到的是,这个人工智能服务是一个带有@RegisterAiService注释的接口。Quarkus扩展提供的注释处理器将生成实现该接口的类。为了能够处理请求,任何会话LLM都需要定义场景或范围。

在这个例子中,其范围是一个专门创作俳句的艺术家的范围。这是@SystemMessage注释的作用:设置当前作用域。最后但并非最不重要的是,@UserMessage注释允许定义为人工智能服务提示的特定文本。在这里请求人工智能服务就一个主题撰写俳句,该主题由类型为String的输入参数subject定义。

基础设施模块

在检查人工智能服务的实现之后,还要了解如何设置所需的基础设施。基础设施模块名为infra,是一个maven子项目,使用Docker -compose实用程序启动以下Docker容器:

一个名为ollama的Docker容器正在运行一个标记为nicolasduminil/ollama:llama2的图像。这个图像只是官方的Ollama Docker图像,它已经被增强以包含Llama2 LLM。如上所述,Ollama能够在本地运行多个LLM,为了使这些LLM可用,需要从它们的Docker注册表中提取。这就是在运行Ollama官方Docker容器时通常需要提取所选的LLM的原因。为了避免这种重复操作,扩展这个官方Docker容器,使其已经包含了Llama2 LLM。

一个名为haiku的Docker容器正在运行标记为quarkus-llm/haiku的图像,这正是人工智能服务。

以下是创建上述基础设施所需的相关docker-compose.yaml文件:

YAML 
1 version: "3.7"
2 services:
3  ollama:
4    image: nicolasduminil/ollama:llama2
5    hostname: ollama
6    container_name: ollama
7    ports:
8      - "11434:11434"
9    expose:
10      - 11434
11  haiku:
12    image: quarkus-llm/haiku:1.0-SNAPSHOT
13    depends_on:
14      - ollama
15    hostname: haiku
16    container_name: haiku
17    links:
18      - ollama:ollama
19    ports:
20      - "8080:8080"
21    environment:
22      JAVA_DEBUG: "true"
23      JAVA_APP_DIR: /home/jboss
24      JAVA_APP_JAR: quarkus-run.jar

可以看到,ollama服务运行在一个DNS名称为ollama的节点上,并监听TCP端口号11434。因此,人工智能服务需要适当地配置以连接到相同的节点/端口。同样,应用属性(application.properties)文件用于此目的,如下所示:

Properties files
1 quarkus.langchain4j.ollama.base-url=http://ollama:11434

这个声明意味着AI服务将把它的请求发送到URL: http://ollama:11434,其中ollama被DNS服务转换为IP地址,该IP地址被分配给同名的Docker容器。

运行和测试

为了运行和测试这个示例项目,可以按照以下步骤进行:

1.克隆存储库:

Shell 
1 $ git clone https://github.com/nicolasduminil/llm-java.git

2.持续交付(cd)到项目:

Shell
1 $ mvn clean install

3.构建项目:

Shell
1 $ mvn clean install

4.检查所有必需的容器是否正在运行:

Shell 
1  $ docker ps
2  CONTAINER ID   IMAGE                            COMMAND                  CREATED         STATUS         PORTS                                                 NAMES
3 19006601c908   quarkus-llm/haiku:1.0-SNAPSHOT   "/opt/jboss/containe…"   5 seconds ago   Up 4 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 8443/tcp   haiku
4 602e6bb06aa9   nicolasduminil/ollama:llama2     "/bin/ollama serve"      5 seconds ago   Up 4 seconds   0.0.0.0:11434->11434/tcp, :::11434->11434/tcp         ollama

5.运行open-api接口来测试服务。启动首选浏览器:http://localhost:8080/q/swaggerui。在显示的标有Haiku API的Swagger会话框中,单击GET按钮并使用Try it函数执行测试。在标题为“主题”(Subject)的文本字段中,键入希望人工智能服务撰写俳句的主题名称,或保留默认名称(即samurai)。测试结果如下图所示:

使用Quarkus和LangChain4j,LLM在Java中可以实现哪些功能?-AI.x社区

也可以通过使用curl工具向人工智能服务发送GET请求来测试项目,如下所示:

Shell 
1 $ curl http://localhost:8080/haiku?subject=quarkus
2 Quarkus, tiny gem
3 In the cosmic sea of space
4 Glints like a star

结语

在以上的项目演示中,探索了LLM的发展历史,并使用LangChain4J实现了企业级Java服务和组件,这些服务和组件由最具主导地位和影响力的LLM提供支持。

原文标题:The Power of LLMs in Java: Leveraging Quarkus and LangChain4j,作者:Nicolas Duminil

链接:https://dzone.com/articles/leveraging-the-llm-power-in-java。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
相关推荐