Alimentando LLMs com Apache Camel e LangChain4j

LLMs precisam se conectar ao mundo real. As ferramentas LangChain4j, combinadas com o Apache Camel, tornam isso fácil. O Camel fornece integração robusta, conectando seu LLM a qualquer serviço ou API. Isso permite que sua IA interaja com bancos de dados, filas e muito mais, criando aplicativos verdadeiramente poderosos. Vamos explorar essa combinação poderosa e seu potencial.

Configurando o Ambiente de Desenvolvimento

  • Ollama: Fornece uma maneira de executar grandes modelos de linguagem (LLMs) localmente. Você pode executar muitos modelos, como LLama3, Mistral, CodeLlama e muitos outros em sua máquina, com suporte total de CPU e GPU.
  • Visual Studio Code: Com os plugins Kaoto, Java e Quarkus instalados.
  • OpenJDK 21
  • Maven
  • Quarkus 3.17
  • Serviços de Desenvolvimento do Quarkus: Um recurso do Quarkus que simplifica o desenvolvimento e teste de aplicativos que dependem de serviços externos, como bancos de dados, sistemas de mensagens e outros recursos.

Você pode baixar o código completo no seguinte repositório do GitHub.

As seguintes instruções serão executadas no Visual Studio Code:

1. Criando o Projeto 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. Adicionando Extensões Quarkus 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. Configurando o Ollama para Executar o LLM do Ollama

Abra o arquivo application.properties e adicione as seguintes linhas:

Properties files

 

#Configurar modelo local do 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

O Quarkus usa o Ollama para executar o LLM localmente e também configurar automaticamente a configuração para uso nos componentes do Apache Camel nas etapas seguintes.

4. Criando Rota do Apache Camel Usando Kaoto

Crie uma nova pasta chamada route na pasta src/main/resources .

Crie um novo arquivo na pasta src/main/resources/routes e nomeie route-main.camel.yaml, e o Visual Studio Code abre o editor visual Kaoto.

Clique no botão +Novo e uma nova rota será criada.

Clique nas setas circulares para substituir o componente do temporizador.

Pesquise e selecione o componente platform-http no catálogo.

Configure as propriedades necessárias do platform-http:

  • Defina o caminho com o valor /camel/chat

Por padrão, o platform-http estará servindo na porta 8080.

Clique no  ícone Adicionar Passo na seta após o componente platform-http.

Pesquise e selecione o componente langchain4j-tools no catálogo.

Configure as propriedades necessárias do langchain4j-tools:

  • Defina Tool Id com o valor meus-ferramentas.
  • Defina Tags com armazenar (Definir tags é para agrupar as ferramentas a serem usadas com o LLM).

Você deve processar a mensagem de entrada do usuário para o componente langchain4j-tools para que possa ser usado, então clique no ícone Adicionar Passo na seta após o componente platform-http.

Pesquise e selecione o componente Processar no catálogo.

Configure as propriedades necessárias:

  • Defina Ref com o valor createChatMessage.

O componente de processo usará o método createChatMessage que você criará na próxima etapa.

5. Crie um Processo para Enviar a Entrada do Usuário para o LLM

Crie uma nova Classe Java na pasta src/main/java chamada 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 {
        // As rotas estão sendo carregadas em arquivos 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);
            }
        };
    }
}

Esta classe ajuda a criar um Processador Camel para transformar a entrada do usuário em um objeto que pode manipular o componente langchain4j na rota. Ela também fornece contexto ao LLM para usar ferramentas e explica a tarefa do Agente.

6. Criando Ferramentas Apache Camel para Usar com LLM

Crie um novo arquivo na pasta src/main/resources/routes e nomeie-o como route-tool-products.camel.yaml, e no Visual Studio Code, abra o editor visual Kaoto.

Clique no botão +Novo, e uma nova rota será criada.

Clique nas setas circulares para substituir o componente timer.

Pesquise e selecione o componente langchain4j-tools no catálogo.

Configure langchain4j-tools, clique na aba Todos e busque as propriedades do Endpoint.

  • Defina Tool Id com o valor productsbycategoryandcolor.
  • Defina Tags com store (o mesmo que na rota principal).
  • Defina Description com o valor Consultar produtos do banco de dados por categoria e cor (uma breve descrição da ferramenta).


Adicione parâmetros que serão usados pela ferramenta:

  • NOME: categoria, VALOR: string
  • NOME: cor, VALOR: string

Esses parâmetros serão atribuídos pelo LLM para uso na ferramenta e são passados via cabeçalho.

Adicione um componente SQL para consultar o banco de dados, em seguida, clique em Adicionar Passo após o componente langchain4j-tools.

Busque e selecione componente SQL.

Configure as propriedades SQL necessárias:

  • Consulta com o seguinte valor.
SQL

 

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

Gerencie os parâmetros para usar na consulta, em seguida, adicione um componente Converter Cabeçalho para converter os parâmetros em um tipo de objeto correto.

Clique no botão Adicionar Passo após langchain4j-tools, busque e selecione a transformação Converter Cabeçalho Para no catálogo.

Configure as propriedades necessárias para o componente:

  • Nome com o valor categoria
  • Tipo com o valor String


Repita os passos com os seguintes valores:

  • Nome com o valor cor
  • Tipo com o valor String

Como resultado, é assim que a rota se parece:

Finalmente, você precisa transformar o resultado da consulta em um objeto que o LLM pode lidar; neste exemplo, você o transforma em JSON.

Clique no botão Adicionar Etapa após o Componente SQL e adicione o componente Marshal.

Configure as propriedades do formato de dados para o Marshal e selecione JSon na lista.

7. Configure os Serviços de Desenvolvimento Quarkus para PostgreSQL

Adicione a extensão Quarkus para fornecer o PostgreSQL para fins de desenvolvimento, execute o seguinte comando no terminal.

Shell

 

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

Abra application.properties e adicione as seguintes linhas:

Properties files

 

#Configurando devservices para 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

Finalmente, crie nosso script SQL para carregar o banco de dados.

Crie uma pasta chamada db em src/main/resources, e nesta pasta, crie um arquivo chamado schema-init.sql  com o seguinte conteúdo.

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. Inclua nossa Rota para ser Carregada pelo Projeto Quarkus

O Camel Quarkus suporta várias linguagens específicas de domínio (DSLs) na definição de Rotas Camel.

Também é possível incluir rotas YAML DSL, adicionando a seguinte linha no arquivo application.properties.

Properties files

 

# rotas a serem carregadas
camel.main.routes-include-pattern = routes/*.yaml

Isso carregará todas as rotas na pasta src/main/resources/routes.

9. Teste o App

Execute a aplicação usando o Maven, abra um Terminal no Visual Studio Code e execute o seguinte comando.

Shell

 

mvn quarkus:dev

Uma vez iniciado, o Quarkus chama o Ollama e executa seu LLM localmente, abre um terminal e verifica com o seguinte comando.

Shell

 

ollama ps

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

Além disso, o Quarkus cria um contêiner executando PostgreSQL e cria um banco de dados e um esquema. Você pode se conectar usando o comando psql.

Shell

 

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

E consultar a tabela de produtos:

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)

Para testar o app, envie uma requisição POST para localhost:8080/camel/chat com um corpo de texto simples. solicitando algum produto.

O LLM pode ter alucinado. Por favor, tente novamente modificando sua solicitação ligeiramente. 

Você pode ver como o LLM usa a ferramenta e obtém informações do banco de dados usando a solicitação em linguagem natural fornecida. O LLM identifica os parâmetros e os envia para a ferramenta. Se você olhar no log de requisições, poderá encontrar as ferramentas e os parâmetros que o LLM está usando para criar a resposta.

Conclusão

Você explorou como aproveitar o poder dos LLMs dentro dos seus fluxos de integração usando o Apache Camel e o componente LangChain4j. Vimos como essa combinação permite que você integre perfeitamente poderosos modelos de linguagem nas suas rotas existentes do Camel, possibilitando a construção de aplicações sofisticadas que podem entender, gerar e interagir com a linguagem humana.

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