Alimentando LLMs com Apache Camel e LangChain4j

Os LLMs precisam se conectar ao mundo real. As ferramentas LangChain4j, combinadas com o Apache Camel, facilitam isso. O Camel fornece uma 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 aplicações verdadeiramente poderosas. 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 a CPU e GPU.
  • Visual Studio Code: Com os plugins Kaoto, Java e Quarkus instalados.
  • OpenJDK 21
  • Maven
  • Quarkus 3.17
  • Serviços de Desenvolvimento Quarkus: Um recurso do Quarkus que simplifica o desenvolvimento e teste de aplicações 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 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 para uso nos componentes do Apache Camel nos seguintes passos.

4. Criando Rota 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 como route-main.camel.yaml, e o Visual Studio Code abrirá 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 do 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 Etapa 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 utilizado, em seguida, clique no ícone Adicionar Etapa 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 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 carregando 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. Também dá ao LLM contexto 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 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 procure as propriedades do Endpoint.

  • Defina ID da Ferramenta com o valor produtosporcategoriaecor.
  • Defina Tags com loja (O mesmo que na rota principal).
  • Defina Descrição 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 utilizados pela ferramenta:

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

Esses parâmetros serão atribuídos pela 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 Etapa após o componente langchain4j-tools.

Pesquise e selecione o 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) 

Manipule os parâmetros para usar na consulta, em seguida adicione um Componente de Conversão de Cabeçalho para converter parâmetros em um tipo de objeto correto.

Clique no botão Adicionar Etapa após langchain4j-tools, pesquise 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 fica:

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

Clique no botão Adicionar Passo 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 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 dentro dessa 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 carregar
camel.main.routes-include-pattern = routes/*.yaml

Isto irá 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

Assim que iniciar, o Quarkus chama o Ollama e executa o 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 o PostgreSQL e cria um banco de dados e 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 aplicativo, envie uma solicitação POST para localhost:8080/camel/chat com um corpo de texto simples. solicitando por algum produto.

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

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

Conclusão

Você explorou como aproveitar o poder dos LLMs dentro de seus fluxos de integração usando o Apache Camel e o componente LangChain4j. Vimos como essa combinação permite que você integre perfeitamente modelos de linguagem poderosos em 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