Saltar al contenido principal
La generación aumentada por recuperación, o RAG, es uno de los patrones más útiles para construir aplicaciones de IA que necesitan responder a partir de tus propios documentos. En lugar de pedir a un modelo que confíe solo en su memoria, primero recuperas material fuente relevante, envías ese contexto al modelo y le pides que responda con citas. En este tutorial, construiremos un bot RAG privado usando Python, Venice para embeddings y chat completions, Qdrant para búsqueda vectorial y FastEmbed para re-ranking local. Al final, tendrás las piezas centrales para un asistente local de documentos que puede ingerir tus archivos, recuperar chunks relevantes, re-ranquearlos y responder con citas. El bot RAG en acción Antes de continuar: si quieres ejecutar el código de este artículo, necesitarás una API key de Venice. Expórtala como variable de entorno:
¿Te interesa la implementación completa del código? Consulta el repositorio de GitHub.

Cómo funciona un bot RAG moderno

Una buena pipeline de RAG es más que “meter documentos en una base de datos vectorial”. El flujo básico se ve así: El paso de re-ranking es el upgrade que hace que esto sea más útil que una demo básica de RAG. La búsqueda vectorial es rápida y buena encontrando chunks semánticamente similares, pero aún puede devolver pasajes adyacentes al tema en lugar de directamente útiles. Un cross-encoder lee la pregunta y cada chunk candidato juntos, y luego puntúa qué tan bien ese chunk responde realmente la pregunta.

Instalar las dependencias

Usaremos el SDK de Python de OpenAI porque Venice expone una API compatible con OpenAI. También usaremos el cliente de Python de Qdrant con soporte para FastEmbed:
Si prefieres mantener las dependencias en un archivo, crea requirements.txt con los mismos paquetes:

Eligiendo los modelos

Crea un archivo llamado rag_bot.py y empieza añadiendo los imports, las estructuras de datos, la URL de la API y los nombres de modelo:
El nombre del modelo de embedding es intencionadamente compatible con OpenAI. Venice mapea nombres de modelos de embedding compatibles con OpenAI a modelos de embedding alojados por Venice, de modo que el código existente del SDK de OpenAI suele poder migrarse cambiando base_url y la API key. Puedes listar los modelos disponibles de Venice con:
Para modelos de chat:

Creando los clientes de Venice y Qdrant

Crea un cliente compatible con OpenAI de Venice tanto para embeddings como para chat completions:
Para Qdrant, tienes tres modos útiles: Para un bot local privado, empieza con una ruta local en disco de Qdrant:
Hay varias formas de gestionar el despliegue en producción. Sin embargo, si usas un despliegue remoto de Qdrant, recuerda que tus chunks de documentos y metadatos se almacenarán allí. Venice puede mantener la capa de inferencia privada, pero aun así deberías elegir el despliegue de Qdrant adecuado para tus datos.

Cargando y chunkeando documentos

Para este tutorial, dejaremos que el bot ingiera archivos o carpetas locales. Empieza con archivos .md, .rst y .txt:
Una vez cargados los archivos, necesitamos dividir el texto haciendo “chunking” — separándolo en trozos de datos. Una estrategia ingenua podría dividir los chunks de forma uniforme. Sin embargo, en la mayoría de los casos esto puede perder información en límites semánticos dados, lo que puede hacer que la efectividad de tu sistema RAG baje. La estrategia de chunking que usaremos prefiere los límites de párrafo o frase para que el modelo obtenga contexto coherente:
Un tamaño de chunk inicial de 1000 caracteres con 150 caracteres de solapamiento es un buen valor por defecto para documentos mixtos de Markdown y texto. Chunks más pequeños pueden mejorar la precisión. Chunks más grandes pueden preservar más contexto. El ajuste correcto a menudo dependerá de los tipos de documentos que estés almacenando.

Hacer embedding de documentos con Venice

Una vez tenemos los chunks, los embedemos por lotes:
El batching importa. Embed de un chunk por vez es simple, pero añade latencia evitable. Mantén el tamaño del batch configurable para poder ajustar el throughput según tu carga de trabajo.

Almacenar vectores en Qdrant

Antes de insertar puntos, crea una colección de Qdrant con el tamaño de vector adecuado. La forma más fácil de conocer el tamaño del vector es embed del primer lote y luego usar len(embeddings[0]).
Cada punto almacena el vector más los metadatos del payload. El payload incluye el texto original y una ruta de origen para que la respuesta pueda citar de dónde vino el contexto:
Usa UUIDs deterministas derivados de source, chunk_index y el contenido. Eso hace que la ingesta repetida sea idempotente para chunks que no han cambiado.

Recuperando chunks candidatos

En tiempo de pregunta, el bot hace embed de la pregunta del usuario y pide a Qdrant los mejores matches vectoriales:
El limit aquí es el número de candidatos. Suele ser mayor que el número de chunks que planeas enviar al modelo, porque el siguiente paso los va a re-ranquear. Un buen valor por defecto es recuperar 8 candidatos y enviar los mejores 4 al modelo de chat.

Re-ranking con FastEmbed

Ahora añadimos la parte que hace que la recuperación se sienta mucho más inteligente.
La diferencia importante entre búsqueda por embedding y re-ranking con cross-encoder es cómo se hace la puntuación. La búsqueda por embedding compara un vector de la pregunta contra un vector por cada chunk. Es rápida y escalable. Un cross-encoder evalúa la pregunta y el chunk juntos. Es más lento, pero puede juzgar la relevancia de forma más directa. Por eso el patrón habitual es:
  1. Recuperar un conjunto mayor de candidatos con búsqueda vectorial.
  2. Re-ranquear solo esos candidatos localmente.
  3. Enviar los pocos mejores chunks al modelo de lenguaje.
Un buen punto de partida es candidate_k=8 y top_k=4. Aumenta candidate_k si la fuente correcta a menudo está cerca pero no llega al contexto final.

Responder con Venice Chat Completions

Una vez seleccionado el contexto, formatéalo con números de fuente:
Después envía el contexto a un modelo de chat de Venice:
Fíjate en el system prompt: se le dice al bot que responda solo a partir del contexto proporcionado. Esa es una protección simple pero importante. Un asistente RAG no debería responder con seguridad desde el conocimiento general del modelo cuando los documentos recuperados no apoyan la respuesta.

Ejecutando el bot

Una vez que ensambles las piezas en un script, guárdalo como rag_bot.py. Una primera ejecución simple puede usar unos pocos documentos de muestra integrados para que puedas verificar la pipeline antes de ingerir tus propios archivos:
Para ingerir tus propios documentos:
Para mantener una colección local de Qdrant en disco e iniciar un chat interactivo:
El script imprime la respuesta y luego las fuentes con las puntuaciones vectorial y de re-ranking:
Si quieres inspeccionar el texto real pasado al modelo, añade:

Opciones útiles de CLI

Expón los principales mandos de recuperación como opciones de CLI para que puedas ajustar el bot sin editar código: Para desarrollo local repetido, un flujo común es:
Luego haz preguntas de seguimiento sin volver a ingerir:

Notas de privacidad

Para una configuración RAG privada, piensa en cada capa por separado: El default más privado para este tutorial es Venice para inferencia, Qdrant local en disco y re-ranking local con FastEmbed. Eso te da un bot RAG práctico sin enviar los payloads de tu base de datos vectorial a un store vectorial de terceros.

Errores comunes a gestionar de antemano

Si cambias de modelos de embedding, recrea la colección de Qdrant. Distintos modelos de embedding pueden producir vectores con distintas dimensiones y las colecciones de Qdrant esperan un tamaño de vector fijo.

A dónde ir después

Una vez tengas la línea base funcionando, las mejoras de mayor impacto suelen ser:
  • Añadir loaders específicos para PDFs, HTML, tickets o páginas internas de wiki.
  • Almacenar metadatos más ricos como títulos, encabezados, fechas, propietarios y URLs.
  • Ajustar candidate_k, top_k, tamaño de chunk y solapamiento con preguntas reales.
  • Añadir preguntas de evaluación para poder medir la calidad de la recuperación antes y después de los cambios.
  • Hacer streaming del chat completion final de Venice para una mejor experiencia de chat interactivo.
Los sistemas RAG son fáciles de demostrar y sorprendentemente fáciles de hacer mediocres. El patrón de búsqueda vectorial + re-ranking es una base sólida porque mantiene la recuperación rápida al tiempo que da al bot una mejor oportunidad de enviar al modelo de lenguaje el contexto correcto.