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.
¿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:
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.
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"}
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.
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.