使用Quarkus和LangChain4j,LLM在Java中可以實現哪些功能?
譯文本文試圖通過一個有趣的原創項目,利用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發生了一個重要的范式轉變,包括采用統計方法取代基于規則的方法。與試圖定義和構建語法的原有模型不同,新模型旨在通過“訓練”來“學習”語言模式?,F在,大量文檔被用來為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程序來執行自然語言任務。為此選擇的用例是實現一個能夠編寫俳句的人工智能服務?!洞笥倏迫珪穼τ谫骄涞亩x是:俳句是一種不押韻的詩歌形式,由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定義。
基礎設施模塊
在檢查人工智能服務的實現之后,還要了解如何設置所需的基礎設施?;A設施模塊名為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容器。
運行和測試
為了運行和測試這個示例項目,可以按照以下步驟進行:
克隆存儲庫:
Shell
1 $ git clone https://github.com/nicolasduminil/llm-java.git
持續交付(cd)到項目:
Shell
1 $ mvn clean install
構建項目:
Shell
1 $ mvn clean install
檢查所有必需的容器是否正在運行:
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
運行open-api接口來測試服務。啟動首選瀏覽器:http://localhost:8080/q/swaggerui。在顯示的標有Haiku API的Swagger會話框中,單擊GET按鈕并使用Try it函數執行測試。在標題為“主題”(Subject)的文本字段中,鍵入希望人工智能服務撰寫俳句的主題名稱,或保留默認名稱(即samurai)。測試結果如下圖所示:
也可以通過使用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。