Alimentare LLM con Apache Camel e LangChain4j

LLM deve connettersi al mondo reale. Gli strumenti LangChain4j, combinati con Apache Camel, rendono questo processo semplice. Camel fornisce un’integrazione robusta, collegando il tuo LLM a qualsiasi servizio o API. Questo consente al tuo intelligenza artificiale di interagire con database, code e altro ancora, creando applicazioni veramente potenti. Esploreremo questa potente combinazione e il suo potenziale.

Configurazione dell’ambiente di sviluppo

  • Ollama: Fornisce un modo per eseguire modelli linguistici di grandi dimensioni (LLM) in locale. Puoi eseguire molti modelli, come LLama3, Mistral, CodeLlama e molti altri sul tuo computer, con pieno supporto CPU e GPU.
  • Visual Studio Code: Con i plugin Kaoto, Java e Quarkus installati.
  • OpenJDK 21
  • Maven
  • Quarkus 3.17
  • Servizi di sviluppo Quarkus: Una funzionalità di Quarkus che semplifica lo sviluppo e il testing di applicazioni che dipendono da servizi esterni come database, sistemi di messaggistica e altre risorse.

Puoi scaricare il codice completo nel seguente repository GitHub.

Le seguenti istruzioni saranno eseguite su Visual Studio Code:

1. Creazione del Progetto 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. Aggiunta delle Estensioni Quarkus di langchain4j

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. Configura Ollama per Eseguire Ollama LLM

Apri il file application.properties e aggiungi le seguenti righe:

Properties files

 

#Configura il modello locale di 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 utilizza Ollama per eseguire LLM localmente e configurare automaticamente l’utilizzo nei componenti Apache camel nei passaggi successivi.

4. Creazione del Percorso Apache Camel Utilizzando Kaoto

Crea una nuova cartella chiamata route nella cartella src/main/resources.

Crea un nuovo file nella cartella src/main/resources/routes e chiamalo route-main.camel.yaml, e Visual Studio Code aprirà l’editor visuale Kaoto.

Fare clic sul pulsante +Nuovo e verrà creata una nuova route.

Fare clic sulle frecce circolari per sostituire il componente timer.

Cercare e selezionare il componente platform-http dal catalogo.

Configurare le proprietà richieste di platform-http:

  • Impostare il percorso con il valore /camel/chat

Per impostazione predefinita, platform-http sarà in esecuzione sulla porta 8080.

Fare clic su  l’icona Aggiungi Passaggio nella freccia dopo il componente platform-http.

Cercare e selezionare il componente langchain4j-tools nel catalogo.

Configurare le proprietà richieste di langchain4j-tools:

  • Impostare Id Strumento con il valore my-tools.
  • Impostare Tag con store (Definire i tag serve per raggruppare gli strumenti da utilizzare con il LLM).

È necessario elaborare il messaggio di input dell’utente per rendere il componente langchain4j-tools in grado di utilizzarlo, quindi fare clic sull’icona Aggiungi Passaggio nella freccia dopo il componente platform-http.

Cercare e selezionare il componente Processo nel catalogo.

Configurare le proprietà richieste:

  • Imposta Ref con il valore createChatMessage.

Il componente di processo utilizzerà il metodo createChatMessage che creerai nel prossimo passaggio.

5. Crea un Processo per Inviare l’Input dell’Utente a LLM

Crea una nuova Classe Java nella cartella src/main/java chiamata 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 {
        // I percorsi vengono caricati nei file 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);
            }
        };
    }
}

Questa classe aiuta a creare un Processore Camel per trasformare l’input dell’utente in un oggetto che può gestire il componente langchain4j nel percorso. Fornisce inoltre il contesto LLM per l’utilizzo degli strumenti e spiega il compito dell’Agente.

6. Creazione di Strumenti Apache Camel per l’Utilizzo con LLM

Crea un nuovo file nella cartella src/main/resources/routes e chiamalo route-tool-products.camel.yaml, e in Visual Studio Code, apri l’editor visuale Kaoto.

Fai clic sul pulsante +Nuovo, e verrà creato un nuovo percorso.

Fai clic sulle frecce circolari per sostituire il componente timer.

Cerca e seleziona il componente langchain4j-tools nel catalogo.

Configurare langchain4j-tools, fare clic sulla scheda Tutti e cercare le proprietà dell’Endpoint.

  • Impostare Tool Id con il valore productsbycategoryandcolor.
  • Impostare Tags con store (lo stesso della route principale).
  • Impostare Descrizione con il valore Query database prodotti per categoria e colore (una breve descrizione del tool).


Aggiungere i parametri che verranno utilizzati dal tool:

  • NOME: category, VALORE: string
  • NOME: color, VALORE: string

Questi parametri verranno assegnati dal LLM per l’uso nel tool e vengono passati tramite header.

Aggiungere il componente SQL per interrogare il database, quindi fare clic su Aggiungi Passaggio dopo il componente langchain4j-tools.

Cercare e selezionare il componente SQL.

Configurare le proprietà SQL richieste:

  • Interrogazione con il seguente valore.
SQL

 

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

Gestire i parametri da utilizzare nella query, quindi aggiungere un componente Converti Header per convertire i parametri in un tipo di oggetto corretto.

Fare clic sul pulsante Aggiungi Passaggio dopo langchain4j-tools, cercare e selezionare la trasformazione Converti Header To nel catalogo.

Configurare le proprietà richieste per il componente:

  • Nome con il valore categoria
  • Tipo con il valore Stringa


Ripetere i passaggi con i seguenti valori:

  • Nome con il valore colore
  • Tipo con il valore Stringa

Come risultato, così appare la route:

Infine, è necessario trasformare il risultato della query in un oggetto che può gestire il LLM; in questo esempio, trasformarlo in JSON.

Fare clic sul pulsante Aggiungi passo dopo il componente SQL e aggiungere il componente Marshal.

Configurare le proprietà del formato dati per il componente Marshal e selezionare JSon dalla lista.

7. Configurare i servizi di sviluppo Quarkus per PostgreSQL

Aggiungere un’ estensione Quarkus per fornire PostgreSQL a scopi di sviluppo, eseguire il comando seguente nel terminale.

Shell

 

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

Aprire application.properties e aggiungere le seguenti righe:

Properties files

 

#Configurazione dei servizi di sviluppo per 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

Infine, creare lo script SQL per caricare il database.

Creare una cartella chiamata db  in src/main/resources, e all’interno di questa cartella, creare un file chiamato schema-init.sql  con il seguente contenuto.

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. Includere la nostra Route da caricare nel progetto Quarkus

Camel Quarkus supporta diversi linguaggi specifici del dominio (DSL) nella definizione delle Route Camel.

È anche possibile includere percorsi yaml DSL, aggiungendo la seguente riga nel file application.properties.

Properties files

 

# percorsi da caricare
camel.main.routes-include-pattern = routes/*.yaml

Questo caricherà tutti i percorsi nella cartella src/main/resources/routes.

9. Test dell’App

Esegui l’applicazione usando Maven, apri un Terminale in Visual Studio Code e esegui il seguente comando.

Shell

 

mvn quarkus:dev

Una volta avviato, Quarkus chiama Ollama ed esegue il tuo LLM in locale, apre un terminale e verifica con il seguente comando.

Shell

 

ollama ps

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

Inoltre, Quarkus crea un contenitore che esegue PostgreSQL e crea un database e uno schema. Puoi connetterti usando il comando psql.

Shell

 

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

E esegui una query sulla tabella dei prodotti:

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)

Per testare l’applicazione, invia una richiesta POST a localhost:8080/camel/chat con un corpo di testo semplice, richiedendo qualche prodotto.

Il LLM potrebbe aver avuto un’allucinazione. Ti preghiamo di riprovare modificando leggermente la tua richiesta.

Puoi vedere come il LLM utilizza lo strumento e ottiene informazioni dal database utilizzando la richiesta in linguaggio naturale fornita. Il LLM identifica i parametri e li invia allo strumento. Se controlli il registro delle richieste, puoi trovare gli strumenti e i parametri che il LLM sta usando per creare la risposta.

Conclusione

Hai esplorato come sfruttare il potere dei LLM all’interno dei tuoi flussi di integrazione utilizzando Apache Camel e il componente LangChain4j. Abbiamo visto come questa combinazione ti permetta di integrare senza soluzione di continuità potenti modelli di linguaggio nei tuoi percorsi Camel esistenti, consentendoti di sviluppare applicazioni sofisticate in grado di comprendere, generare e interagire con il linguaggio umano.

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