Navegación principal

¿Puede Postgres gestionar tu proceso de RAG?

Probamos el enfoque de pgai centrado en la base de datos para comprobar dónde simplifica las operaciones de RAG y dónde las cargas complejas aún necesitan más flexibilidad.

Resumen ejecutivo

  • Los LLM solo pueden «ver» una cantidad limitada de texto a la vez (la ventana de contexto). Esto funciona para tareas pequeñas, pero deja de ser eficaz cuando una base de conocimiento abarca miles de páginas. Aunque la ventana de contexto sea suficiente, el rendimiento puede deteriorarse por el problema de «buscar una aguja en un pajar».

  • RAG («generación aumentada por recuperación») se ha convertido en un patrón muy habitual: se mantiene una base de conocimiento (documentación, wikis, políticas, transcripciones, etc.), se realiza una búsqueda semántica a partir de la consulta del usuario para recuperar mediante embeddings los fragmentos más relevantes y, después, se proporcionan esos fragmentos al LLM junto con la pregunta. Esto acota el contexto del modelo y, si se hace correctamente, puede mejorar la calidad de las respuestas y reducir las alucinaciones.

  • pgai es una extensión de código abierto para Postgres, acompañada de herramientas, que ayuda a crear flujos de trabajo de «recuperación con IA» sobre PostgreSQL, la fiable base de datos de código abierto.

  • La idea principal es trasladar una mayor parte del proceso estándar de RAG a la capa de base de datos (ingesta → fragmentación → creación de embeddings → sincronización de embeddings), en lugar de tratar la base de datos como «un mero almacén» de embeddings.

  • Nuestra primera impresión es que resulta prometedor, pero deja de ser adecuado en cuanto el proceso de RAG adquiere cierta complejidad, sobre todo en los métodos de fragmentación. No obstante, seguiremos muy de cerca este proyecto.

El patrón RAG

Hay muchas formas de crear un sistema RAG. Para consultar un análisis más extenso de los distintos enfoques, lee Ejemplos prácticos de soluciones RAG personalizadas. Las posibilidades de diseño adquieren una profundidad sorprendente cuando importa la calidad, pero el enfoque «predeterminado» suele ser este:

  1. Reunir un conjunto de documentos.

  2. Dividirlos en fragmentos. Hay muchos métodos para hacerlo (por ejemplo, por párrafos o agrupaciones semánticas).

  3. Convertir cada fragmento en un embedding.

  4. Almacenar los embeddings en una base de datos vectorial (Pinecone, Milvus, etc.) o en Postgres mediante pgvector.

  5. Al recibir una consulta, buscar los fragmentos más próximos `y proporcionárselos al LLM (de nuevo, también hay muchas formas de hacerlo).

En muchas arquitecturas, los pasos (1)–(3) se ejecutan fuera de la base de datos, en el código de la aplicación o en un proceso de datos, y la base de datos se utiliza principalmente para:

  • almacenar embeddings

  • buscar embeddings

Finalidad de pgai

pgai es una extensión de código abierto para Postgres, desarrollada por Timescale), que trata de difuminar esa frontera.

En vez de tratar los embeddings como algo que la aplicación gestiona manualmente, pgai los convierte en una función de la base de datos:

  • Se define qué tabla o documentos se quieren convertir en embeddings.

  • Se especifican el modelo de embeddings y una estrategia de fragmentación.

  • pgai se encarga del resto, incluida la actualización de los embeddings cuando cambian los datos de origen.

La propuesta resulta atractiva:

  • Menos código de integración específico que mantener.

  • Debería facilitar que los embeddings se mantengan «actualizados» cuando cambien los documentos de origen.

  • Postgres/pgai gestiona los reintentos, los límites de solicitudes, los trabajos fallidos, etc.

Nota para quien lea: pgai incorpora pgvector, otra extensión muy popular de Postgres para RAG. pgvector añade almacenamiento vectorial y búsqueda por similitud a Postgres, mientras que pgai se basa en ello para automatizar pasos del proceso de RAG, como la fragmentación, la creación de embeddings y su actualización.

Primeras impresiones sobre pgai

Lo que nos gustó

1) Es fácil ponerlo en marcha.

El proceso ideal es bastante sencillo:

  • Descargar las imágenes de Docker de Timescale (base de datos + worker).

  • Proporcionar la clave de API del proveedor de embeddings.

  • Ejecutar unas pocas instrucciones SQL para declarar el vectorizador (básicamente, qué convertir en embeddings, cómo fragmentarlo y qué modelo usar).

A partir de ahí, pgai hace que un worker de vectorización se ejecute como proceso independiente y genere embeddings de forma asíncrona (por ejemplo, cada 5 minutos o con la frecuencia deseada).

2) Resulta práctico ejecutar todo el proceso «cerca» de la base de datos.

pgai puede ingerir contenido de tablas y cargar documentos desde ubicaciones como S3 para después analizarlos, fragmentarlos y convertirlos en embeddings. También admite distintos formatos de documentos de texto, como PDF, Markdown, etc.

Lo que nos pareció limitado

1) Se pierde mucho control, y RAG a veces lo necesita.

Los sistemas RAG de alto rendimiento, medido por la calidad de las respuestas, suelen requerir procesos personalizados, como:

  • reglas de fragmentación personalizadas (por encabezados, páginas, turnos de palabra, etc.)

  • fragmentación que tenga en cuenta los metadatos (conservar títulos de secciones, marcas de tiempo, autores y tipo de documento)

  • distintas estrategias de embeddings según el tipo de documento

pgai ofrece menos flexibilidad para todo lo anterior.

Por ahora, existen dos estrategias principales de fragmentación: un divisor de texto por caracteres y otro recursivo por caracteres, además de una opción sin fragmentación. Puede bastar para algunos casos de uso, pero muchos sistemas RAG en producción requieren una mayor personalización.

Sería fantástico que Timescale incorporase algunas de las estrategias de fragmentación más sofisticadas presentes en bibliotecas como Chonkie y ofreciese también diseños avanzados como la recuperación contextual de Anthropic.

2) Prioriza el texto, no la multimodalidad.

Muchos problemas interesantes de RAG ya no se limitan al texto:

  • PDF con diagramas

  • capturas de pantalla e imágenes

  • grabaciones de audio

  • clips de vídeo

Aunque se pueda «extraer texto» de estas fuentes, eso no equivale a un verdadero proceso multimodal de embeddings.

Si pgai acaba admitiendo modelos multimodales de principio a fin (cargar → fragmentar → crear embeddings para imágenes, audios o vídeos grandes almacenados en S3, con una sincronización sólida), sería muy atractivo. Sin embargo, hoy es un flujo de trabajo de embeddings de texto.

3) Si solo necesitas embeddings, quizá no necesites pgai.

Si tu proceso de ingesta ya está personalizado, o necesita estarlo, «crear embeddings de fragmentos de texto» no es la parte más difícil de RAG. En ese contexto, pgai resuelve la parte más sencilla del problema.

Además, si la base de conocimiento se actualiza con poca frecuencia, la sincronización automática de embeddings aporta menos valor.

Capa de texto a SQL

Una forma especialmente útil de emplear pgai sería implementar una interfaz de texto a SQL sobre las bases de datos. Esto se puede conseguir con bastante facilidad mediante el módulo semantic_catalog que ofrece pgai. Basta con configurarlo así:

Bash

OPENAI_API_KEY="your-OpenAPI-key-goes-here"TARGET_DB="postgres://user:password@host:port/database"CATALOG_DB="postgres://user:password@host:port/database"

y hacer que el catálogo semántico examine los diccionarios de datos con pgai semantic-catalog create. Esto genera un contexto a partir del almacén de datos con un aspecto similar al siguiente:

Plain Text

---schema: postgres_airname: aircrafttype: tabledescription: Lists aircraft models with performance characteristics and unique codes.columns:- name: model  description: Commercial name of the aircraft model.- name: range  description: Maximum flight range in kilometers.- name: class  description: Airframe class category or configuration indicator.- name: velocity  description: Cruising speed of the aircraft.- name: code  description: Three-character aircraft code serving as the primary key....

Este contexto queda disponible para pgai de varias formas:

Mediante búsqueda semántica:

Esta consulta devolverá las tablas, funciones y demás objetos que puedan ser relevantes para tu consulta en lenguaje natural:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!"

Obtener el contexto sin procesar:

Esto mostrará el contexto YAML sin procesar relacionado con tu consulta en lenguaje natural:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!" --render

Generar SQL:

También puedes generar directamente el SQL sin procesar necesario para responder a tu consulta. El contexto del paso anterior se envía a un LLM, que genera la respuesta:

Bash

pgai semantic-catalog generate-sql -p "Your natural language question goes here!"

Cómo usar pgai ahora mismo

Si estás creando un sistema RAG relativamente sencillo, merece la pena probar pgai si buscas:

  • usar Postgres como sistema de registro,

  • un mínimo de código de integración,

  • embeddings que se mantengan sincronizados automáticamente,

  • una forma rápida de aplicar texto a SQL a tus bases de datos,

  • experimentar con nuevas herramientas de RAG y extensiones de Postgres.

Cuándo actuaríamos con cautela

Probablemente convenga esperar antes de usar pgai si tu proceso de RAG necesita alguna de estas funciones:

  • lógica de ingesta o fragmentación muy personalizada

  • muchos tipos de documentos con distintos requisitos de análisis

  • embeddings multimodales

Por último, aunque está claro que pgvector ha logrado una gran adopción, no se sabe si pgai despertará el mismo interés y, por tanto, recibirá un nivel de soporte similar, si bien solo existe desde hace unos 18 meses.

Gráfico del historial de estrellas de GitHub que muestra la adopción de pgai de Timescale a lo largo del tiempo.

Resumen

pgai plantea un enfoque interesante para RAG: permitir que las bases de datos asuman más tareas operativas rutinarias y simplificar así el código de la aplicación.

Actualmente:

  • es útil y realmente agradable para configuraciones RAG sencillas

  • no ofrece suficiente flexibilidad para procesos más personalizados, especialmente multimodales

Resulta prometedor y, sin duda, merece la pena seguir su evolución.

Autor

Andrew Liubinas