使用Apache Camel和LangChain4j为LLMs提供動力

LLMs 需要與現實世界連接。LangChain4j 工具結合 Apache Camel,使這一切變得簡單。Camel 提供強大的整合能力,將您的 LLM 連接到任何服務或 API。這讓您的 AI 能夠與資料庫、佇列等進行互動,創造真正強大的應用程式。我們將探索這一強大組合及其潛力。

設置開發環境

  • Ollama:提供在本地運行大型語言模型 (LLMs) 的方法。您可以在您的機器上運行 許多模型,例如 LLama3、Mistral、CodeLlama 等,並支持完整的 CPU 和 GPU。
  • Visual Studio Code:安裝了 Kaoto、Java 和 Quarkus 插件。
  • OpenJDK 21
  • Maven
  • Quarkus 3.17
  • Quarkus 開發服務:是 Quarkus 的一項功能,簡化依賴於外部服務(例如資料庫、消息系統和其他資源)的應用程式的開發和測試。

您可以在以下的 GitHub 倉庫 下載完整的代碼。

以下指示將在 Visual Studio Code 上執行:

1. 創建 Quarkus 專案

Shell

 

mvn io.quarkus:quarkus-maven-plugin:3.17.6:create \
-DprojectGroupId=dev.mikeintoch \
-DprojectArtifactId=camel-agent-tools \
-Dextensions="camel-quarkus-core,camel-quarkus-langchain4j-chat,camel-quarkus-langchain4j-tools,camel-quarkus-platform-http,camel-quarkus-yaml-dsl"

2. 添加 langchain4j Quarkus 擴展

Shell

 

./mvnw quarkus:add-extension -Dextensions="io.quarkiverse.langchain4j:quarkus-langchain4j-core:0.22.0"
./mvnw quarkus:add-extension -Dextensions="io.quarkiverse.langchain4j:quarkus-langchain4j-ollama:0.22.0"

3. 配置 Ollama 以運行 Ollama LLM

打開 application.properties  文件並添加以下行:

Properties files

 

#配置 Ollama 本地模型
quarkus.langchain4j.ollama.chat-model.model-id=qwen2.5:0.5b

quarkus.langchain4j.ollama.chat-model.temperature=0.0
quarkus.langchain4j.ollama.log-requests=true
quarkus.langchain4j.log-responses=true
quarkus.langchain4j.ollama.timeout=180s

Quarkus 使用 Ollama 在本地運行 LLM,並在接下來的步驟中自動配置 Apache camel 組件的使用。

4. 使用 Kaoto 創建 Apache Camel 路由

src/main/resources  文件夾中創建一個名為 route 的新文件夾。

src/main/resources/routes 文件夾中創建一個新文件,並命名為 route-main.camel.yaml,Visual Studio Code 將打開 Kaoto 視覺編輯器

點擊 +新建 按鈕,將創建一個新的路由。

點擊圓形箭頭以替換計時器組件。

從目錄中搜索並選擇 platform-http 組件。

配置所需的 platform-http 屬性:

  • 將路徑設置為 /camel/chat

默認情況下,platform-http 將在 8080 端口上提供服務。

點擊 添加步驟圖標 的箭頭後面。

在目錄中搜索並選擇 langchain4j-tools 組件。

配置所需的 langchain4j-tools 屬性:

  • 工具 ID 設置為 my-tools
  • 標籤 設置為 store(定義 標籤 是為了將工具分組以便與 LLM 一起使用)。

您必須處理用戶輸入消息,使其能夠使用 langchain4j-tools 組件,然後點擊 添加步驟圖標platform-http 組件後的箭頭上。

在目錄中搜索並選擇 處理 組件。

配置所需的屬性:

  • 設定Ref為值createChatMessage

處理元件將使用您在接下來的步驟中創建的createChatMessage方法。

5. 創建一個流程以將用戶輸入發送到LLM

src/main/java資料夾中創建一個新的Java類,命名為Bindings.java

Java

 

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

import org.apache.camel.BindToRegistry;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;

import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;

public class Bindings extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        // 路由在yaml文件中加載。
    }


    @BindToRegistry(lazy=true)
    public static Processor createChatMessage(){

        return new Processor() {
            public void process(Exchange exchange) throws Exception{

                String payload = exchange.getMessage().getBody(String.class);
                List messages = new ArrayList<>();

                String systemMessage = """
                    You are an intelligent store assistant. Users will ask you questions about store product. 
                    Your task is to provide accurate and concise answers.

                    In the store have shirts, dresses, pants, shoes with no specific category

                    %s

                    If you are unable to access the tools to answer the user's query, 
                    Tell the user that the requested information is not available at this time and that they can try again later.
                        
                    """;

                String tools = """
                        You have access to a collection of tools
                        You can use multiple tools at the same time
                        Complete your answer using data obtained from the tools
                        """;

                messages.add(new SystemMessage(systemMessage.formatted(tools)));


                messages.add(new UserMessage(payload));

                exchange.getIn().setBody(messages);
            }
        };
    }
}

此類幫助創建一個Camel處理器以將用戶輸入轉換為可以在路由中處理langchain4j元件的對象。它還為LLM提供使用工具的上下文,並解釋代理的任務。

6. 創建Apache Camel工具以用於LLM

src/main/resources/routes資料夾中創建一個新文件,命名為route-tool-products.camel.yaml 並在Visual Studio Code中打開Kaoto可視化編輯器。

點擊 +新建按鈕,將創建一條新路由。

點擊圓形箭頭以替換計時器元件。

在目錄中搜索並選擇langchain4j-tools元件。

配置 langchain4j-tools,點擊全部選項卡並搜索端點屬性。

  • 工具 ID設置為值productsbycategoryandcolor
  • 標籤設置為 商店(與主路由中相同)
  • 描述設置為值 按類別和顏色查詢數據庫產品(工具的簡要描述)


添加工具將使用的參數:

  • 名稱: 類別,值:字符串
  • 名稱:顏色,值:字符串

這些參數將由 LLM 分配給工具使用,並通過標頭傳遞。

添加 SQL 組件以查詢數據庫,然後在langchain4j-tools組件後點擊添加步驟

搜索並選擇SQL 組件

配置所需的 SQL 屬性:

  • 使用以下值進行查詢。
SQL

 

Select  name, description, category, size, color, price, stock from products where Lower(category)= Lower (:#category) and Lower(color) = Lower(:#color) 

處理要在查詢中使用的參數,然後添加轉換標頭組件將參數轉換為正確的對象類型。

langchain4j-tools後點擊添加步驟按鈕,搜索並選擇目錄中的轉換標頭為轉換。

配置組件所需的屬性:

  • 名稱的值為 category
  • 類型的值為 String


重複以下值的步驟:

  • 名稱的值為 color
  • 類型的值為 String

結果是這樣的路由:

最後,您需要將查詢結果轉換為 LLM 可以處理的對象;在這個例子中,您將其轉換為 JSON。

在 SQL 組件後,單擊 添加步驟按鈕,並添加 Marshal 組件

為 Marshal 配置數據格式屬性,並從列表中選擇 JSon

7. 配置 Quarkus Dev Services 以支援 PostgreSQL

添加 Quarkus 擴展以提供 PostgreSQL 用於開發目的,請在終端中運行以下命令。

Shell

 

./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-jdbc-postgresql"

打開 application.properties 並添加以下行:

Properties files

 

#為 Postgresql 配置開發服務
quarkus.datasource.db-kind=postgresql
quarkus.datasource.devservices.port=5432
quarkus.datasource.devservices.init-script-path=db/schema-init.sql
quarkus.datasource.devservices.db-name=store

最後,創建我們的 SQL 腳本以加載數據庫。

src/main/resources 中創建一個名為 db 的文件夾,並在此文件夾中創建一個名為 schema-init.sql 的文件,內容如下。

SQL

 

DROP TABLE IF EXISTS products;

CREATE TABLE IF NOT EXISTS products (
    id SERIAL NOT NULL,
    name VARCHAR(100) NOT NULL,
    description varchar(150),
    category VARCHAR(50),
    size VARCHAR(20),
    color VARCHAR(20),
    price DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL,
    CONSTRAINT products_pk PRIMARY KEY (id)
);

    INSERT INTO products (name, description, category, size, color, price, stock)
VALUES
    ('Blue shirt', 'Cotton shirt, short-sleeved', 'Shirts', 'M', 'Blue', 29.99, 10),
    ('Black pants', 'Jeans, high waisted', 'Pants', '32', 'Black', 49.99, 5),
    ('White Sneakers', 'Sneakers', 'Shoes', '40', 'White', 69.99, 8),
    ('Floral Dress', 'Summer dress, floral print, thin straps.', 'Dress', 'M', 'Pink', 39.99, 12),
    ('Skinny Jeans', 'Dark denim jeans, high waist, skinny fit.', 'Pants', '28', 'Blue', 44.99, 18),
    ('White Sneakers', 'Casual sneakers, rubber sole, minimalist design.', 'Shoes', '40', 'White', 59.99, 10),
    ('Beige Chinos', 'Casual dress pants, straight cut, elastic waist.', 'Pants', '32', 'Beige', 39.99, 15),
    ('White Dress Shirt', 'Cotton shirt, long sleeves, classic collar.', 'Shirts', 'M', 'White', 29.99, 20),
    ('Brown Hiking Boots', 'Waterproof boots, rubber sole, perfect for hiking.', 'Shoes', '42', 'Brown', 89.99, 7),
    ('Distressed Jeans', 'Distressed denim jeans, mid-rise, regular fit.', 'Pants', '30', 'Blue', 49.99, 12);

8. 包含我們的路由以供 Quarkus 項目加載

Camel Quarkus 支援幾種特定領域的語言 (DSL) 來定義 Camel 路由。

也可以包含 YAML DSL 路由,在 application.properties 文件中添加以下行。

Properties files

 

# 要加載的路由
camel.main.routes-include-pattern = routes/*.yaml

這將加載 src/main/resources/routes 資料夾中的所有路由。

9. 測試應用程式

使用 Maven 運行應用程式,在 Visual Studio Code 中打開終端,並運行以下命令。

Shell

 

mvn quarkus:dev

一旦啟動,Quarkus 會調用 Ollama 並在本地運行你的 LLM,打開一個終端並使用以下命令進行驗證。

Shell

 

ollama ps

NAME            ID              SIZE      PROCESSOR    UNTIL
qwen2.5:0.5b    a8b0c5157701    1.4 GB    100% GPU     4 minutes from now

此外,Quarkus 會創建一個運行 PostgreSQL 的容器,並創建一個數據庫和模式。你可以使用 psql 命令進行連接。

Shell

 

psql -h localhost -p 5432 -U quarkus -d store

並查詢產品表:

Shell

 

store=# select * from products;
 id |        name        |                    description                     | category | size | color | price | stock
----+--------------------+----------------------------------------------------+----------+------+-------+-------+-------
  1 | Blue shirt         | Cotton shirt, short-sleeved                        | Shirts   | M    | Blue  | 29.99 |    10
  2 | Black pants        | Jeans, high waisted                                | Pants    | 32   | Black | 49.99 |     5
  3 | White Sneakers     | Sneakers                                           | Shoes    | 40   | White | 69.99 |     8
  4 | Floral Dress       | Summer dress, floral print, thin straps.           | Dress    | M    | Pink  | 39.99 |    12
  5 | Skinny Jeans       | Dark denim jeans, high waist, skinny fit.          | Pants    | 28   | Blue  | 44.99 |    18
  6 | White Sneakers     | Casual sneakers, rubber sole, minimalist design.   | Shoes    | 40   | White | 59.99 |    10
  7 | Beige Chinos       | Casual dress pants, straight cut, elastic waist.   | Pants    | 32   | Beige | 39.99 |    15
  8 | White Dress Shirt  | Cotton shirt, long sleeves, classic collar.        | Shirts   | M    | White | 29.99 |    20
  9 | Brown Hiking Boots | Waterproof boots, rubber sole, perfect for hiking. | Shoes    | 42   | Brown | 89.99 |     7
 10 | Distressed Jeans   | Distressed denim jeans, mid-rise, regular fit.     | Pants    | 30   | Blue  | 49.99 |    12
(10 rows)

要測試應用程式,向 localhost:8080/camel/chat  發送 POST 請求,並提供純文本主體輸入,請求一些產品。

LLM 可能會出現幻覺。請稍微修改你的請求再試一次。

你可以看到 LLM 如何使用工具並根據提供的自然語言請求從數據庫中獲取信息。LLM 辨識參數並將其發送到工具。如果你查看請求日誌,你可以找到 LLM 用於生成答案的工具和參數。

結論

您已經探索了如何在整合流程中利用大型語言模型(LLMs)的力量,使用 Apache Camel 和 LangChain4j 組件。我們已經看到這種組合如何讓您無縫地將強大的語言模型整合到現有的 Camel 路由中,使您能夠構建能夠理解、生成和與人類語言互動的精密應用程序。

Source:
https://dzone.com/articles/powering-llms-with-apache-camel-and-langchain4j