📙 En una serie de múltiples partes sobre la creación de aplicaciones web con integración generativa de IA. La Parte 1 se centró en discutir la pila AI y por qué la capa de aplicación es el mejor lugar en la pila. Compruébalo aquí fuera. La Parte 2 se centró en por qué Ruby es el mejor lenguaje web para construir MVP de IA. Compruébalo aquí fuera. Le recomiendo que lea ambas partes antes de leer este artículo para atrapar a la terminología utilizada aquí.
Tabla de contenido
Introducción
En este artículo, llevaremos a cabo un divertido experimento mental. Buscamos responder a la pregunta:
¿Qué tan simple podemos hacer una aplicación web con integración de IA?
Mis lectores sabrán que valoro Simplicidad muy alta. Las aplicaciones web simples son más fáciles de entender, más rápido de construir y más mantenibles. Por supuesto, a medida que la aplicación escala, la complejidad surge de la necesidad. Pero siempre quieres comenzar simple.
Tomaremos un estudio de caso típico para una aplicación web con integración de IA (RAG) y analizaremos cuatro implementaciones diferentes. Vamos a comenzar con la configuración más compleja que se compone de las herramientas más populares e intentaremos simplificarlo paso a paso, hasta que terminemos con la configuración más simple posible.
¿Por qué estamos haciendo esto?
Quiero inspirar a los desarrolladores a pensar más simplemente. A menudo, la ruta “convencional” para crear aplicaciones web o integrar IA es demasiado compleja para el caso de uso. Los desarrolladores se inspiran en compañías como Google o Apple, sin reconocer que las herramientas que funcionan para ellos son a menudo inapropiadas para los clientes que trabajan a una escala mucho más pequeña.
Tome un café o té, y vamos a sumergirnos.
Nivel 1: tan complejo como se vuelve
Supongamos que un cliente le ha pedido que cree una aplicación de trapo para ellos. Esta aplicación tendrá una página donde los usuarios pueden cargar sus documentos y otra página donde puedan chatear con sus documentos usando RAG. Ir con la pila web más popular actualmente en uso, decide ir con el Mierda pila (MongoDB, Express.js, React y Node.js) para construir su aplicación.
Para construir las tuberías de RAG que manejarán los documentos de análisis, fragmentos, incrustaciones, recuperación y más, nuevamente decide ir con la pila más popular: Langchain desplegado a través de Fastapi. La aplicación web hará llamadas API a los puntos finales definidos en Fastapi. Deberá haber al menos dos puntos finales: uno para llamar a la tubería de indexación y otro para llamar a la tubería de consulta. En la práctica, también necesitará Upsert y Eliminar puntos finales, para garantizar que los datos en su base de datos permanezcan sincronizados con los incrustaciones en su tienda vectorial.
Tenga en cuenta que usará JavaScript para la aplicación web y Python para la integración de AI. Esta aplicación de dúo-lingüe significa que probablemente usará un Microservicios arquitectura (ver Parte 2 de esta serie para más información sobre esto). Este no es un requisito estricto, pero a menudo se alienta en una configuración como esta.
Hay una opción más: ¿Qué base de datos vectorial usará? La base de datos de Vector es el lugar donde almacena los fragmentos de documentos creados por la tubería de indexación. Vamos a ir de nuevo con la elección más popular: Piña. Esta es una base de datos de vector de nube administrada que muchos desarrolladores de IA están utilizando actualmente.
Todo el sistema podría parecerse a lo siguiente:
¡Ay! Hay muchas piezas móviles aquí. Desglosemos las cosas:
- En el rectángulo inferior, tenemos la aplicación web y el backend de MongoDB. En el medio tenemos las tuberías de trapo construidas con Langchain y Fastapi. En la parte superior, tenemos la base de datos de Vector Pinecone. Cada rectángulo aquí representa un servicio diferente con sus propias implementaciones separadas. Mientras se administrará la base de datos de Vector de Cloud Cloud, el resto está en usted.
- He envuelto las solicitudes HTTP de ejemplo y las respuestas correspondientes con un borde punteado. Recuerde, esta es una arquitectura de microservicios, por lo que esto significa que las solicitudes HTTP se necesitarán en cualquier momento que ocurra la comunicación entre servicios. Para simplificar, solo he ilustrado cómo se vería las llamadas de la tubería de consulta y he omitido cualquier llamada a OpenAi, antrópica, etc. Para mayor claridad, contuve las solicitudes/respuestas en el orden en que ocurrirían en un escenario de consulta.
- Para ilustrar un punto de dolor, garantizar que los documentos en su base de datos MongoDB se sincronicen con sus incrustaciones correspondientes en el índice Pinecone es factible pero puede ser complicado. Se necesitan múltiples solicitudes HTTP para pasar de su base de datos MongoDB a la base de datos de Vector Cloud. Este es un punto de complejidad y sobrecarga para el desarrollador.
Una analogía simple: esto es como tratar de mantener su estantería física sincronizada con un catálogo de libros digitales. Cada vez que obtienes un nuevo libro o donas un libro de tu estante (resulta que solo te gusta el Game of Thrones Muestre, no el libro), debe ir y actualizar manualmente el catálogo para reflejar el cambio. En este mundo de libros, una pequeña discrepancia realmente no te afectará, pero en el mundo de las aplicaciones web este puede ser un gran problema.
Nivel 2: Deja caer la nube
¿Podemos hacer que esta arquitectura sea más simple? Quizás lea un artículo recientemente que discutió cómo Postgres tiene una extensión llamada pgvector. Esto significa que puede renunciar a Pinecone y simplemente usar Postgres como su base de datos vectorial. Idealmente, puede migrar sus datos desde MongoDB para que permanezca con una sola base de datos. ¡Excelente! Refactoras tu solicitud para que ahora parezca lo siguiente:
Ahora solo tenemos dos servicios de los que preocuparse: la base de datos de la aplicación web + y las tuberías de RAG. Una vez más, se ha omitido cualquier llamada a los proveedores de modelos.
¿Qué hemos ganado con esta simplificación? Ahora tu Los incrustaciones y los documentos o fragmentos asociados pueden vivir en la misma tabla en la misma base de datos. Como ejemplo, puede agregar una columna de incrustaciones a una tabla en PostgreSQL haciendo:
ALTER TABLE documents
ADD COLUMN embedding vector(1536);
Mantener la coherencia entre los documentos y los incrustaciones debería ser mucho más simple ahora. Postgres ‘ ON INSERT/UPDATE desencadenantes te permiten calcular incrustaciones en el lugar, eliminando las dos fases “Escribe doc/luego incrustar” bailar por completo.
Volviendo a la analogía de la estantería, esto es como abandonar el catálogo digital y, en su lugar, simplemente adjuntar una etiqueta directamente a cada libro. Ahora, cuando se mueve por un libro o arroja uno, no hay necesidad de actualizar un sistema separado, ya que las etiquetas van a donde sea que vayan los libros.
Nivel 3: ¡Microservices se rompen!
Has hecho un buen trabajo simplificando las cosas. Sin embargo, crees que puedes hacerlo aún mejor. Quizás puedas crear un aplicación monolítica, en lugar de usar la arquitectura de microservicios. Un monolito solo significa que su aplicación y sus tuberías de trapo se desarrollan e implementan juntos. Sin embargo, surge un problema. Codificó la aplicación web en JavaScript utilizando la pila MERN. Pero las tuberías de RAG se construyeron con Python y Langchain desplegados a través de Fastapi. Quizás pueda intentar exprimirlos en un solo contenedor, usando algo como Supervisor Para supervisar los procesos de Python y JavaScript, pero no es un ajuste natural para las pilas políglotas.
Entonces, lo que decide hacer es deshacerse de React/Node y, en su lugar, usar Django, un marco web de Python para desarrollar su aplicación. Ahora, su código de tuberías RAG puede vivir en un módulo de utilidad en su aplicación Django. Esto significa que no se están realizando más solicitudes HTTP, lo que elimina la complejidad y la latencia. Cada vez que desee ejecutar su consulta o indexar tuberías, todo lo que tiene que hacer es hacer una llamada de función. Girar entornos e implementaciones de desarrollo es ahora una brisa. Por supuesto, si lees la Parte 2, nuestra preferencia no es usar una pila All Python, sino que vaya con un todo Ruby Stack.
Has simplificado aún más y ahora tiene la siguiente arquitectura:
Una nota importante: en diagramas anteriores, combiné la aplicación web y la base de datos en un solo servicio, por simplicidad. ¡En este punto, creo que es importante demostrar que, de hecho, son servicios separados! Esto hace no Significa que todavía estás usando una arquitectura de microservicios. Mientras los dos servicios se desarrollen e implementen por completo, este sigue siendo un monolito.
¡Guau! Ahora solo tiene una sola implementación para girar y mantener. Puede configurar su base de datos como accesorio para su aplicación web. Lamentablemente, esto significa que probablemente querrá usar Docker componer Para desarrollar e implementar su base de datos y servicios de aplicaciones web juntos. Pero con las tuberías ahora solo funcionan como funciones en lugar de un servicio separado, ¡ahora puede abandonar Fastapi! Ya no necesitará mantener estos puntos finales; Solo use llamadas de funciones.
Un poco de detalle técnico: en este gráfico, la leyenda indica que la línea punteada es no Http, pero en cambio un Postgres Frontend/Backend Protocol. Estos son dos protocolos diferentes en el capa de aplicación del modelo de protocolo de Internet. Esta es una capa de aplicación diferente a la que discutí en Parte 1. El uso de una conexión HTTP para transferir datos entre la aplicación y la base de datos es teóricamente posible, pero no óptima. En cambio, los creadores de Postgres crearon su propio protocolo que es delgado y está bien acoplado a las necesidades de la base de datos.
Nivel 4: SQLite entra en el chat
“¿Seguramente hemos terminado de simplificar?”puede que se esté preguntando.
¡Equivocado!
Hay una simplificación más que podemos hacer. En lugar de usar Postgres, ¡podemos usar SQLite! Verá, actualmente su aplicación y su base de datos son dos servicios separados implementados juntos. Pero, ¿qué pasaría si no fueran dos servicios diferentes, sino que su base de datos era solo un archivo que vive en su aplicación? Esto es lo que SQLite puede darle. Con el recientemente lanzado sqlite-vec biblioteca, incluso puede manejar el trapo, al igual que cómo pgvector Funciona para Postgres. La advertencia aquí es que sqlite-vec es pre-v1, pero esto sigue siendo excelente para una etapa temprana MVP.
Verdaderamente sorprendente. ¡Ahora puedes abandonar Ditch Docker! Este es realmente un solo servicio Aplicación web. Los módulos LangChain y su base de datos ahora son solo funciones y archivos que viven en su repositorio.
¿Preocupado por el uso de SQLite en una aplicación web de producción? I escribió recientemente Sobre cómo SQLite, una vez considerado solo un juguete en el mundo de las aplicaciones web, puede estar listo para la producción a través de algunos ajustes en su configuración. De hecho, Ruby on Rails 8 recientemente hizo que estas adaptaciones estén predeterminadas y ahora está presionando a SQLite como un base de datos predeterminada para nuevas aplicaciones. Por supuesto, a medida que la aplicación se escala, es probable que deba migrar a Postgres o alguna otra base de datos, pero recuerde el mantra que mencioné al principio: solo introduzca la complejidad cuando sea absolutamente necesario. No asuma que su aplicación explotará con millones de escrituras concurrentes cuando solo intenta obtener a sus primeros usuarios.
Resumen
En este artículo, comenzamos con las pilas tradicionales para construir una aplicación web con integración de IA. Vimos la cantidad de complejidad involucrada y decidimos simplificar la pieza por pieza hasta que terminamos con el ideal platónico de aplicaciones simples.
Pero no dejes que la simplicidad te engañe; La aplicación sigue siendo una bestia. De hecho, debido a la simplicidad, puede funcionar mucho más rápido que la aplicación tradicional. Si está notando que la aplicación está comenzando a disminuir, intentaría densar el servidor antes de considerar la migración a una nueva base de datos o romper el monolito.
Con una aplicación tan delgada, realmente puede moverse rápido. El desarrollo local es un sueño, y se puede agregar nuevas capacidades a la velocidad del rayo. Todavía puede obtener copias de seguridad de su base de datos SQLite usando algo como Litroam. Una vez que su aplicación muestre signos reales de tensión, avance los niveles de complejidad. Pero aconsejo que no comenzar una nueva aplicación en el nivel 1.
Espero que hayas disfrutado de esta serie sobre la creación de aplicaciones web con integración de IA. ¡Y espero haberte inspirado a pensar simple, no complicado!
🔥 Si desea una aplicación web personalizada con integración generativa de IA, visite Losangelesaiapps.com