Integra tus sistemas con Gen AI: Flujos de trabajo ágiles con Quarkus y Apache Camel.

Camel
Imagen creada con MetaAI

Introducción.

En términos técnicos, un agente de IA es una entidad de software diseñada para realizar tareas de forma autónoma o semiautónoma en nombre de un usuario o de otro programa. Estos agentes aprovechan la inteligencia artificial para tomar decisiones, emprender acciones e interactuar con su entorno o con otros sistemas.

Los agentes de IA son potentes herramientas que pueden automatizar y mejorar una amplia gama de actividades, desde simples tareas repetitivas hasta complejos escenarios de resolución de problemas, lo que los convierte en una herramienta invaluable en diversas aplicaciones e industrias.

A medida que la IA generativa revolucion a las empresas, surge un nuevo paradigma de software denominado orquestación de agentes. Exploraremos cómo Quarkus y Apache Camel pueden ayudarte a abordar este desafío. Veremos cómo, al combinar la agilidad de Quarkus con la versatilidad de Apache Camel, puedes crear flujos de datos sofisticados que permitan a tus sistemas 'pensar' y tomar decisiones de manera autónoma.

Vayamos de paseo

Se construirá un agente de IA con la capacidad de analizar reseñas de productos y determinar el sentimiento general de los clientes. Para ello, se emplearán las tecnologías Quarkus, Langchain4j y Apache Camel, las cuales permitirán crear un flujo de integración eficiente para el procesamiento de las reseñas.

Llm

¿Qué vamos a necesitar?

Todas las herramientas serán ejecutadas en un entorno local, aprovechando las ventajas que ofrece Quarkus Dev Services.

  • Ollama. Servicio para ejecutar de forma local LLM.
  • Kafka. El servicio de intercambio de mensajes. (Desplegado a través de Quarkus Dev Services.)
  • Podman. Servicio de ejecución nuestros servicios de forma local. (Donde serán desplegados los componentes de Quarkus Dev Services).
  • OpenJDK 21
  • Quarkus 3.16

Puede descargar el código completo en el siguiente enlace

Creando el proyecto de Quarkus.

mvn io.quarkus:quarkus-maven-plugin:3.16.2:create \
-DprojectGroupId=dev.mikeintoch \
-DprojectArtifactId=camel-agent-integration \
-Dextensions="camel-quarkus-core,camel-quarkus-direct,camel-quarkus-bean,quarkus-langchain4j-core,quarkus-langchain4j-ollama,quarkus-langchain4j-core,camel-quarkus-rest,camel-quarkus-jsonpath,camel-quarkus-telegram,camel-quarkus-kafka,camel-quarkus-gson"

Creando nuestro Agente AI con Quarkus.

Es necesario definir el LLM a utilizar y su configuración. Se debe abrir el archivo application.properties y agregar las siguiente líneas:

#Configure Ollama local model
quarkus.langchain4j.ollama.chat-model.model-id=mistral:latest
quarkus.langchain4j.ollama.log-requests=true
quarkus.langchain4j.ollama.timeout=60s

Se utilizará el modelo mistral, pero puede revisar los modelos disponibles que soporta Ollama.

A continuación vamos crear el primer agente de IA. Para ello, se creará una nueva interfaz denominada ReviewAgent.java

package dev.mikeintoch;

import org.apache.camel.Handler;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import io.quarkiverse.langchain4j.RegisterAiService;
import jakarta.enterprise.context.ApplicationScoped;

@RegisterAiService
@ApplicationScoped
public interface ReviewAgent {
    
    @Handler
    @SystemMessage("You are a bot checking if the review is positive or negative. You will always answer with a JSON document, and only this JSON document.")
    @UserMessage("""
        Your task is to process the review delimited by ---.
        Apply a sentiment analysis to the passed review to determine if it is positive or negative.
        The review can be in any language. So, you must need to identify the language.

        For example:
        - "I love your product, you are the best!", this is a POSITIVE review
        - "J'adore votre produit", this is a POSITIVE review
        - "Me gustó mucho el producto", this is a POSITIVE review
        - "I hate your product, you are the worst!", this is a NEGATIVE review
        - "Nunca volveré a comprar el producto", this is a NEGATIVE review


        Answer with a JSON document containing:
        - the 'evaluation' key set to 'POSITIVE' if the review is positive, 'NEGATIVE' otherwise, depending if the review is positive or negative
        - the 'reply' key set to a message thanking the customer in the case of a positive review, or an apology and a note that the bank is going to contact the customer in the case of a negative review. These messages must be polite and use the same language as the passed review.
        - the 'message' key set to the passed review

        ---
        {review}
        ---
        """)
    public UserReview checkReview(String review);
}

Lo importante aquí es la anotación @RegisterAiService, esto le indica a Quarkus que cuando llame al metodo checkReview estará usando el LLM que definimos en las propiedades.

Asimismo, la anotación @SystemMessage sirve para especificar el comportamiento del agente, para definir  la tarea que nuestro agente debe realizar es necesario utilizar la anotación @UserMessage. En este contexto, se encargará de analizar el texto en la propiedad review y como resultado después del analisis generará una respuesta JSON como salida.

Creando nuestra Ruta de Camel para orquestar el agente.

Para dar inicio al desarrollo de nuestra Ruta de Camel, creamos una nueva clase llamada ReviewRoute.java

package dev.mikeintoch;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.JsonLibrary;

import jakarta.inject.Inject;
import jakarta.enterprise.context.ApplicationScoped;


@ApplicationScoped
public class ReviewRoute extends RouteBuilder{

    @Inject
    ReviewAgent aiAgent;

    @Override
    public void configure() throws Exception {
        // Receive reviews from kafka.
        from("kafka:income-reviews")
          .to("direct:aiAgent");
        
        //Quarkus AI Agent receives review and process message
        from("direct:aiAgent")
           .unmarshal().json(JsonLibrary.Gson)
           .log("${body}")
           .bean(aiAgent)
           .log("Agent Answer: ${body}")
           .to("direct:checkEvaluation");

        // Compare response Agent and send to correct NEGATIVE or POSITIVE topic.
        from("direct:checkEvaluation")
          // Convert to Text.
         .marshal().json(JsonLibrary.Gson)
         // Convert to JSon to manipualte
         .unmarshal().json(JsonLibrary.Gson)
         .setHeader("evaluation").simple("${body[evaluation]}")
         .choice()
           .when(header("evaluation").isEqualTo(Evaluation.POSITIVE))
                .to("kafka:positive")
           .otherwise()
               .to("kafka:negative");
    }
    
}

Configuremos el broker de Kafka que usará por defecto nuesta ruta de camel, abra el archivo application.properties y añada la siguiente linea:

#Kafka Camel Configuration
camel.component.kafka.brokers = localhost:9092

Configurando Quarkus Developer Services.

Quarkus Dev Services, es una característica de Quarkus que simplifica el desarrollo y las pruebas de aplicaciones que dependen de servicios externos como bases de datos, sistemas de mensajería y otros recursos.

Agregue la siguiente linea en el archivo application.properties para configurar nuestro broker de Kafka:

# Devservices kafka conf
quarkus.kafka.devservices.port=9092

Ejecutando nuestra aplicación

Ejecuta tu aplicación en modo desarrollo.

mvn quarkus:dev

Una vez que se esté ejecutando, pulsa d en el terminal para abrir la devUI de Quarkus:

Screenshot 2024 11 10 At 12.40.18 a.m.

Debería de ver todas las extensiones incluidas LangChain4j  y Apache Kafka.

Probemos nuestra aplicación

Dentro de la devUI, seleccione Topics en el widget Apache Kafka Client, observará que existe un tópico llamada income-reviews.

Screenshot 2024 11 10 At 12.51.20 a.m.

Clic en el tópico income-reviews y envia un nuevo mensaje al tópico dando clic en el signo '+':

{"review": "I love your product"}

Screenshot 2024 11 10 At 12.54.17 a.m.

En la terminal observará que Apache Camel toma el mensaje y lo envia hacia el LLM:

Request:
- method: POST
- url: http://localhost:11434/api/chat
- headers: [Accept: application/json], [Content-Type: application/json], [User-Agent: Quarkus REST Client], [content-length: 1711]
- body: {
  "model" : "mistral:latest",
  "messages" : [ {
    "role" : "system",
    "content" : "You are a bot checking if the review is positive or negative. You will always answer with a JSON document, and only this JSON document."
  }, {
    "role" : "user",
    "content" : "Your task is to process the review delimited by ---.\nApply a sentiment analysis to the passed review to determine if it is positive or negative.\nThe review can be in any language. So, you must need to identify the language.\n\nFor example:\n- \"I love your product, you are the best!\", this is a POSITIVE review\n- \"J'adore votre produit\", this is a POSITIVE review\n- \"Me gustó mucho el producto\", this is a POSITIVE review\n- \"I hate your bank, you are the worst!\", this is a NEGATIVE review\n- \"Nunca volveré a comprar el producto\", this is a NEGATIVE review\n\n\nAnswer with a JSON document containing:\n- the 'evaluation' key set to 'POSITIVE' if the review is positive, 'NEGATIVE' otherwise, depending if the review is positive or negative\n- the 'reply' key set to a message thanking the customer in the case of a positive review, or an apology and a note that the bank is going to contact the customer in the case of a negative review. These messages must be polite and use the same language as the passed review.\n- the 'message' key set to the passed review\n\n---\n{review=I love your product}\n---\n\nYou must answer strictly in the following JSON format: {\n\"evaluation\": (type: enum, must be one of [POSITIVE, NEGATIVE]),\n\"message\": (type: string),\n\"reply\": (type: string)\n}"
  } ],
  "tools" : [ ],
  "options" : {
    "temperature" : 0.8,
    "top_k" : 40,
    "top_p" : 0.9
  },
  "stream" : false
}

Como resultado el LLM crea un nuevo mensaje JSON, Apache Camel compara el resultado y es depositado en un nuevo topico llamado positive.

Screenshot 2024 11 10 At 1.02.39 a.m.

Puede descargar el código completo en el siguiente enlace

Conclusión

La integración de la IA en nuestras aplicaciones es una tendencia imparable. Con Quarkus, Apache Camel y la IA, estamos dando los primeros pasos hacia un futuro donde las máquinas aprenden y se adaptan a nuestro entorno de forma autónoma.

Si comparamos Apache Camel con otros frameworks de integración, su mayor diferenciador es su amplia gama de conectores. Con más de 300 opciones disponibles podemos integrar prácticamente cualquier sistema sin necesidad de desarrollar conectores personalizados. Al combinarlo con Quarkus y la IA, obtenemos una plataforma de desarrollo completa y poderosa.

Deja una respuesta

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