Conectando LLMs al Mundo Real: Desarrolla LLMs Tools con Apache Camel y LangChain4j.

Whatsapp Image 2024 12 12 At 4.45.43 Pm

Existe un concepto conocido como «tools» o «herramientas». Permite al LLM llamar, cuando sea necesario, a una o más herramientas disponibles, normalmente definidas por el desarrollador. Una herramienta puede ser cualquier cosa: una búsqueda en la web, una llamada a una API externa, la ejecución de un fragmento de código específico, etc. En realidad, los LLM no pueden llamar a la herramienta ellos mismos, sino que expresan la intención de llamar a una herramienta específica en su respuesta (en lugar de responder en texto plano). Nosotros, como desarrolladores, debemos ejecutar esta herramienta con los argumentos proporcionados e informar de los resultados de la ejecución de la herramienta.

Las herramientas LangChain4j, combinadas con Apache Camel, facilitan esta tarea. Camel proporciona una integración robusta, conectando tu LLM a cualquier servicio o API. Esto permite a tu IA interactuar con bases de datos, colas y más, creando aplicaciones realmente potentes. Exploraremos esta poderosa combinación y su potencial.

Configuración del entorno de desarrollo.

  • Ollama. Proporciona una forma de ejecutar localmente Modelos (LLM). Puede ejecutar muchos modelos como LLama3, Mistral, CodeLlama y muchos otros en local, con soporte completo de CPU y GPU.
  • Visual Studio Code. Con los plugins Kaoto, Java y Quarkus instalados.
  • OpenJDK 21
  • Maven
  • Quarkus 3.17
  • Quarkus Dev Services. Característica de Quarkus que simplifica el desarrollo y prueba de aplicaciones el desarrollo y prueba de aplicaciones que dependen de servicios externos como bases de datos, sistemas de mensajería y otros recursos.

Puede descargar el código completo en el siguiente repositorio de Github.

Las siguientes instrucciones se ejecutarán en Visual Studio Code.

1. Creando el proyecto de Quarkus.

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. Añadir extensiones langchain4j de Quarkus.

./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 para ejecutar su LLM.

Abrir el archivo application.properties y agregar las siguientes lineas:

#Configure Ollama local model
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 utiliza Ollama para ejecutar llm localmente y también conecta la configuración para el uso en los componentes de Apache Camel para los siguientes pasos. **

4. Creando su ruta Apache Camel utilizando Kaoto.

Crear un  nuevo directorio nombrado route dentro del directorio src/main/resources.

Crear un nuevo archivo dentro de la carpeta src/main/resources/routes y nómbralo route-main.camel.yaml. Visual Studio Code abrirá el editor visual de Kaoto.

Screenshot 2024 11 22 At 11.40.11 a.m.

Haga clic en el botón +New y se creará una nueva ruta.

Screenshot 2024 12 12 At 5.40.38 p.m.

Haga clic en las flechas circulares para sustituir el componente timer.

Screenshot 2024 12 23 At 1.07.44 p.m.

Busque y seleccione en el catálogo el componente plataform-http.

Screenshot 2024 12 23 At 1.08.51 p.m.

Configurar las propiedades requeridas del componente plataform-http:

  • Establezca el propiedad Path con el valor  /camel/chat

Screenshot 2024 12 23 At 1.13.09 p.m.

Por defecto platform-http servirá en el puerto 8080.

Haga clic en el Icono Add Step en la flecha después del componente plataform-http.

Screenshot 2024 12 23 At 1.14.53 p.m.

Busque y seleccione el componente langhchain4j-tools en el catálogo.

Screenshot 2024 12 23 At 1.18.31 p.m.

Configure las propiedades requeridas de langhchain4j-tools:

  • Establecer Tool Id con el valor my-tools.
  • Establecer Tags con store (Definir tags es para agrupar las herramientas a utilizar con el LLM).

Screenshot 2024 12 23 At 1.22.40 p.m.

Se debe procesar el mensaje de entrada del usuario para que el componente langchain4j-tools sea capaz de manejar. A continuación, haga clic en el icono Add Step en la flecha después del component plataform-http.

Screenshot 2024 12 23 At 1.34.24 p.m.

Busque y seleccione el componente Process en el catálogo.

Screenshot 2024 12 23 At 1.35.33 p.m.

Configure las propiedades requeridas:

  • Establece Ref con el valor createChatMessage.

Screenshot 2024 12 23 At 1.38.21 p.m.

** El componente de Process utilizará el método createChatMessage que se va crear en el siguiente paso. **

5. Crear Proceso para enviar la entrada del usuario al LLM.

Crear una nueva clase Java en la carpeta src/main/java llamada Bindings.java con el siguiente contenido

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 {
        // Routes are loading in yaml files.
    }


    @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<ChatMessage> 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 clase ayuda a crear Camel Processor para transformar la entrada del usuario a un objeto que pueda manejar el componentes langchain4j  en la ruta.

También sirve para dar contexto al LLM para el uso de las tools y cual es la tarea para el Agente **.

6. Creación de herramientas Apache Camel para su uso con LLM.

Crear un nuevo archivo en la carpeta src/main/resources/routes con el nombre route-tool-products.camel,yaml y Visual Studio Code abrirá el editor visual Kaoto.

Screenshot 2024 11 22 At 11.40.11 a.m.

Haga clic en el botón +New y se creará una nueva ruta de Camel.

Screenshot 2024 12 23 At 1.53.48 p.m.

Haga clic en las flechas circulares para sustituir el componente de timer.

 

Screenshot 2024 12 23 At 1.07.44 p.m.

Buscar y seleccionar en el catálogo el componente langchain4j-tools.

Screenshot 2024 12 23 At 1.55.46 p.m.

Configurar langchain4j-tools haga clic en la pestaña All y buscar Endpoint properties.

  • Establecer toolId con el valor productosporcategoríaycolor.
  • Establecer Tags with store (Lo mismo que en la ruta principal).
  • Establecer Description con el valor Query database products by category and color (Una breve descripción de la herramienta).

Screenshot 2024 12 23 At 2.09.36 p.m.

Añada los parámetros que utilizará la herramienta con los siguientes valores:

NAME VALUE
category string
color string

Quedando de la siguiente forma:

Screenshot 2024 12 23 At 2.13.36 p.m.

** Estos parámetros serán asignados por el LLM para su uso en la herramienta y se pasan a través de los headers**.

Añada el componente SQL para consultar la base de datos y haga clic en Add Step después del componente langchain4j-tools.

Screenshot 2024 12 23 At 2.24.20 p.m.

Buscar y seleccionar sql component en el catalogo.

Screenshot 2024 12 23 At 2.26.08 p.m.

Configure las propiedades sql requeridas:

  • Query con el siguiente valor.
Select  name, description, category, size, color, price, stock from products where Lower(category)= Lower (:#category) and Lower(color) = Lower(:#color)

Screenshot 2024 12 23 At 2.29.00 p.m.

Para manejar los parámetros en la consulta añada el componente Convert Header para transformar los parámetros a un tipo de objeto correcto.

Haga clic en el botón Add Step después de langchain4j-tools, busque y seleccione Convert Header To en el catálogo.

Screenshot 2024 12 23 At 4.42.11 p.m.

Configure las propiedades requeridas para el componente:

  • Name con el  valor category
  • Type con el  valor String

Repita los pasos con los valores siguientes:

  • Name con el valor color
  • Type con el valor String

Como resultado, este es el aspecto de la ruta

Screenshot 2024 12 23 At 4.48.58 p.m.

Finalmente necesita transformar el resultado de la consulta a un objeto que el LLM pueda manejar, en este ejemplo usará una transformación a JSON.

Haga clic en el botón Add Step después de SQL Component, y añada el componente Marshal

Screenshot 2024 12 23 At 4.52.23 p.m.

Configure las propiedades del formato de datos para el Marshal, seleccione JSon de la lista.

Screenshot 2024 12 23 At 4.53.55 p.m.

7. Configurar Quarkus Dev Services para PostgreSQL.

Añada la extensión de Quarkus para proporcionar PostgreSQL para propósitos de desarrollo, ejecute el siguiente comando en el terminal.

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

Abra application.properties y añada las siguientes líneas

#Configuring devservices for 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 crear nuestro script sql para cargar la base de datos.

Cree una carpeta llamada db en src/main/resources y en esta carpeta cree un archivo llamado schema-init.sql con el siguiente contenido.

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. Incluir nuestra Ruta para ser cargada por el proyecto de Quarkus.

Camel Quarkus admite varios lenguajes específicos de dominio (DSL) para definir rutas Camel.

También es posible incluir rutas DSL yaml añadiendo la siguiente línea en el archivo application.properties.

# routes to load
camel.main.routes-include-pattern = routes/*.yaml

** Esto cargará todas las rutas en la carpeta src/main/resources/routes . **

9. Probar la aplicación.

Ejecute la aplicación utilizando Maven, abra un Terminal en Visual Studio Code y ejecute el siguiente comando.

mvn quarkus:dev

Una vez que se ha iniciado, Quarkus utiliza ollama y ejecutar localmente el llm, abra un terminal y verifique con el siguiente comando.

ollama ps

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

También Quarkus con ayuda de Podman crea un contenedor que ejecuta postgresql, crea base de datos y esquema. Puede conectarse utilizando el comando psql.

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

Y consulta la tabla de PRODUCTS.

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 probar la aplicación, envíe una solicitud POST a localhost:8080/camel/chat con una entrada de cuerpo de texto sin formato, solicitando algún producto, a continuación un ejemplo.

Screenshot 2024 12 23 At 5.49.20 p.m.

Screenshot 2024 12 23 At 5.50.20 p.m.

** El LLM puede tenes alucinaciones. Por favor, inténtelo de nuevo modificando ligeramente su petición. **

Puede ver como el LLM utiliza la herramienta y obtiene información de la base de datos utilizando la petición proporcionando en lenguaje natural, el LLM identifica los parámetros enviados a la herramienta, si miras en el log sobre la petición puedes encontrar las herramientas y parámetros que el LLM está utilizando para crear la respuesta.

Screenshot 2024 12 23 At 5.52.10 p.m.

Conclusión

Ha explorado como aprovechar la potencia de los LLM en sus flujos de integración utilizando Apache Camel y el componente LangChain4j. Hemos visto cómo esta combinación le permite integrar sin problemas potentes modelos de lenguaje en sus rutas Camel existentes, lo que le permite construir aplicaciones inteligentes que pueden entender, generar e interactuar con el lenguaje natural.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *