logo
Menu
La IA y AWS: Lo que he aprendido al realizar mi proyecto

La IA y AWS: Lo que he aprendido al realizar mi proyecto

Hace aproximadamente 2 meses empecé un pequeño proyecto personal en AWS. Me ha tomado mucho tiempo avanzar pero he aprendido mucho!

Published Apr 28, 2024
Last Modified Apr 30, 2024

Explicación de lo que va a tratar el articulo

En qué consiste el proyecto

Hace aproximadamente 2 meses comencé a desarrollar lo que sería un pequeño proyecto personal tipo "chat" en donde los usuarios, después de iniciar sesión en mi página, podrían realizar consultas relacionadas al tema de derecho laboral y obtener de forma sencilla una respuesta a sus preguntas mediante una inteligencia artificial similar a ChatGPT y con una interfaz tipo chat. Por ello, llamé a mi proyecto abogado-gpt.

Motivación de mi proyecto

Mi principal motivación es que todos tenemos problemas que sabemos que son legales, sin embargo, es difícil encontrar entre un mar de letras la información que necesitamos para resolver nuestro problema y, además, interpretar su contenido no es fácil.
Pero la tecnología en el mundo de la inteligencia artificial y específicamente en el machine learning ha avanzado muchísimo en los últimos años, con nuevos modelos apareciendo en la escena pública cada mes, cada uno más potente y prometedor que el anterior, prometiendo que avanzamos hacia un AGI, por lo que utilizar estas herramientas en favor de la sociedad es un buen ejercicio que beneficia a todos al mismo tiempo que personalmente se adquiere conocimiento nuevo.

Técnicamente que estoy haciendo

En la siguiente imagen muestro una imagen de la arquitectura de mi proyecto y los componentes que he implementado para desarrollar mi idea.
Diagrama de mi proyecto con inteligencia artificial
Diagrama de mi proyecto con inteligencia artificial rag aws bedrock
A pesar de ser un proyecto relativamente pequeño, llevar a la nube mi idea implica crear varios componentes. Esto me ha ayudado a empujar el borde de mi ignorancia para dar espacio a su implementación en mi proyecto. Básicamente tengo en mente 4 componentes principales que se relacionan para dar vida a mi proyecto.
  • El proveedor de identidad de AWS Cognito (aunque me guitaría en un futuro utilizar Facebook para el inicio de sesión).
  • La aplicación de chat tal cuál, lo que incluye el front, el backend y la base de datos de la aplicación.
  • La base de datos de vectores donde almaceno la información de la Ley Federa del Trabajo embebida en forma de vectores.
  • Mi pipeline de despliegue automatizado con AWS Codepipeline con el que despliego mis cambios de forma rápida.
AWS Cognito sirve para la gestión de identidades, mientras que el front-end y el back-end interactúan para que el usuario pueda obtener las respuestas deseadas. La base de datos vectorial es esencial, ya que me permite recuperar información relevante para las preguntas del usuario al transformar la pregunta en un vector (embedding) con el modelo Amazon Titan Embeddings Text y realizar búsquedas de similitud vectorial. Por último, el despliegue del front-end, back-end y la base de datos vectorial lo tengo automatizado con AWS CodePipeline, lo que facilita ciclos de prueba más rápidos.

Qué llevo hecho

Hasta el momento ya tengo una versión muy pobre de un MVP, al menos es relativamente funcional. Ya he implementado los 4 componentes mencionados, por lo que ya es posible iniciar sesión y crear un chat en tiempo real respondido por una inteligencia artificial, específicamente el LLM de Mistral Mixtral 8x7B. Esto involucra por lo tanto tener listo el chat, el pipeline de despliegue y la base de datos de vectores.
A continuación, les muestro una pequeña imagen de cómo se ve el chat y cómo es la respuesta.
Inicio de sesión con AWS Cognito
Inicio de sesión con AWS Cognito
Tenemos un inicio de sesión. Después de esto, podemos entrar a ver nuestra página y ver los chats que hemos tenido. Como es una cuenta nueva, no vemos ninguno.
Pagina principal donde vemos los cats
Pagina principal donde vemos los cats
Ahora, al crear un chat, tenemos que llenar un formulario para que el LLM tenga más contexto del problema y pueda dar una mejor respuesta. En la siguiente imagen muestro un caso hipotético pero es muy posible que se puede dar en cualquier empresa de mala maña.
Formulario de contexto
Formulario de contexto
Por último, el corazón de la aplicación. Un chat donde preguntaremos y recibiremos una respuesta:
Respuesta de un LLM Mixtral 8x7B
Respuesta de un LLM Mixtral 8x7B
Notarán que el chat tiene varios problemas visuales, claro que es algo que tengo que solucionar, pero efectivamente el modelo logró dar una respuesta, buena o no, es discutible, pero es algo. En la respuesta del modelo podemos leer que cita el artículo 133 de la ley federal del trabajo, donde textualmente se puede leer el siguiente fragmento:
[Queda prohibido a los patrones o a sus representantes] I. Negarse a aceptar trabajadores por razón de origen étnico o nacional, género, edad, discapacidad, condición social, condiciones de salud, religión, opiniones, preferencias sexuales, estado civil o cualquier otro criterio que pueda dar lugar a un acto discriminatorio...
Considero esto un gran avance, pues aunque la respuesta no es perfecta, he logrado guiar a este usuario hipotético hacia un artículo relevante de la Ley Federal del Trabajo. Aunque la respuesta no sea la mejor, hay muchas áreas de mejora para ofrecer respuestas más precisas que aún no he implementado. Esta versión de mi aplicación no reemplaza a un profesional, pero su capacidad actual puede considerarse como un pequeño apoyo.

Razón de este post

¿Si aún me falta arreglar cosas, por qué escribo este post? Principalmente porque he aprendido mucho en lo que llevo de este proyecto y quisiera utilizar este post para recordar algunas de estas cosas y así poder compartirlo con ustedes antes de que las olvide.
Entre estas cosas que he aprendido, seguro habrá cosas muy básicas y otras no tanto, pero independientemente de eso, el punto es que yo no lo sabía y me tocó resolverlas, ya sea leyendo la documentación, buscando en mil foros o, ya cuando estaba desesperado, picándole por todos lados.
Así, a continuación, enlisto algunas de estos aprendizajes de forma escueta y ya en la siguiente sección elaboro más.
  • Es posible invocar una función lambda como un trigger al registrase en AWS Cognito.
  • Las lambdas en una subnet pública no tienen acceso a internet por defecto.
  • Existen alternativas del NAT Gateway de AWS que son más económicas y suficientes para muchos casos de uso.
  • Las tareas de un servicio de ECS lanzadas con Fargate utilizan la misma ENI para su creación y para el manejo de la comunicación de la VPC (aún no la solucionó bien).
  • El framework de .NET cuenta con una herramienta llamada SignalR que permite implementar chats en tiempo real de forma MUY sencilla y elegante.
Creo que son los principales, también admito que tuve problemas que logré solucionar sin entender completamente la solución ya que tomaba por cierto lo que encontraba en foros, sin embargo, son los menos. Para este post, me enfocaré únicamente en los retos relacionados a AWS.

Retos a los que me he enfrentado y su solución

Lambda Cognito triggers

A pesar de que podía usar AWS Cognito para el inicio de sesión, por el esquema de base de dato que había definido, necesitaba que el usuario, o al menos parte de su información, como nombre de usuario y correo, vivieran en mi propia base de datos de forma que las entidades de mi base de datos, como los chats y los mensajes pudieran relacionarse.
Cuando te registras en AWS Cognito, usualmente declaras un callback url, donde Cognito hará una redirección, pero antes de esto, puedes activar la configuración de una función lambda triggers, que recibe la información del registro del usuario. Esto es especialmente útil en mi caso, porque utilizo esta información para registrar el usuario en mi propia base de datos con el fin de poder manejar de forma más personalizada los permisos y el perfil del usuario dentro de la aplicación.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const mysql = require("mysql2/promise");

...

const handler = async (event) => {
const defaultResponse = {
statusCode: 400,
body: "Internal Server Error",
};
...
try {
const connection = await mysql.createConnection({
host: MYSQL_HOST,
user: MYSQL_USER,
database: MYSQL_DB,
port: 3306,
password: MYSQL_PWD,
});
const creationDate = new Date().toISOString();
const [res] = await connection.query(
"INSERT INTO users (username, email, created_at) VALUES (?, ?, ?)",
[userName, email, creationDate]
);

await connection.end();
return event;

} catch (err) {
console.log(err);
}
};

module.exports = { handler };
Así de fácil estoy registrando al usuario en la base de datos propia de la aplicación, por lo que en mis entidades ya puedo relacionar mis usuarios con sus chats y mensajes.

Las lambdas lanzadas en subnets públicas no tienen acceso a internet

Empecé configurando mi función lambda en una subnet pública ya que necesitaba que hiciera unas consultas en la base de datos dentro de la misma VPC, sin embargo, igual requería que consumiera otros servicios de AWS como AWS Bedrock, y también que hiciera peticiones HTTP a mi balanceador de carga que está enfrente de mi backend.
En la imagen pueden ver mi lambda en la subnet publica tratando de consumir mi balanceador por internet (líneas rojas). El tema es que mi VPC para ese tiempo solo tenía salida a internet por el IGW para las subnedes públicas, sin embargo, la lambda no lograba consultar el ALB, lo cual se me hacía extraño.
¿Cómo solucioné esto? El tema es que una función lambda, cuando se lanza dentro de una VPC, no tiene salida a internet de forma predeterminada porque la ENI que se crea para asociar la función a nuestra subnet y por lo tanto que tenga acceso a nuestros recursos privados, no tiene una IP pública asignada y por lo tanto no hay forma de realizar el NAT por medio del Internet Gateway.
Honestamente, esto ya lo sabía desde hace rato, sin embargo, al momento de configurar mi proyecto no lo tenía en mente por lo que tuve que solucionarlo nuevamente. La solución fue sencilla, pasar la lambda a una subnet privada y configurar un NAT Gateway en la subnet pública, así como realizar la configuración de VPC Endpoints de interfaz para el servicio de AWS Bedrock Runtime.

AWS NAT Gateway es muy caro

Como mencioné, para que mi función lambda pudiera comunicarse con mi ALB, necesitaba configurar un NAT Gateway, sin embargo, este componente es carísimo para un proyecto en desarrollo como el mío. Aunque no es un problema técnico, sí representa un problema para mi pobre bolsillo, ¡ya que tiene un precio de alrededor de 0.045 dólares la hora! Más los cargos por transferencia de datos.
En mi búsqueda por solucionarlo encontré fck-nat como una alternativa. Aunque soy una persona muy reservada con el tono de mis palabras, encuentro justificado el nombre, al menos en mi circunstancia, ya que el precio del NAT Gateway me parece exagerado.
Al final de cuentas, fue muy sencillo configurar fck-nat como una instancia de EC2 t4g.nano que me cuesta una 10% del precio del NAT Gateway. ¡Lo único que tuve que hacer es crear una instancia donde use una AMI de fuk-nat y configurarla para que sea lanzada en la subnet pública donde pudiera actuar como destino en las tablas de ruteo de las subnets privada y listo!

Qué me falta

Mucho.
Me falta mucho, sin embargo, considero que tengo ya un buen avance. Entre los pendientes que tengo está refactorizar el backend, arreglar unos bugs en el front y agregar unos cuantos features más que tengo pendientes por crear relacionados a métodos de pago (probablemente use stripe), chats grupales, entre otros.
Por otro lado, sé que me falta mucho de UI y UX, admito que es un mundo por si solo y voy a tener que leer mucho antes de poder hacer algo interesante, pero está entre mis pendientes.

Conclusión

A través de este post, he tratado de dar un panorama general sobre cómo un proyecto personal puede transformarse en una herramienta útil y práctica que aprovecha el poder de la tecnología moderna para resolver problemas cotidianos. Mi proyecto sirve para mostrar cómo la inteligencia artificial y el aprendizaje automático pueden ser aplicados de manera efectiva en el ámbito del derecho laboral para facilitar el acceso a información legal relevante y precisa. Este proyecto no solo ha sido una oportunidad para aplicar conocimientos técnicos avanzados en un contexto real, sino también un proceso de aprendizaje constante frente a los desafíos que surgen al integrar diversas tecnologías como AWS Cognito, AWS CodePipeline, y el manejo de bases de datos vectoriales en un entorno de producción. Los problemas encontrados y las soluciones implementadas demuestran la importancia de la adaptabilidad y la innovación en el desarrollo de software.
 

Comments