Metadatos: el ingrediente que más mejora un RAG

Filtrado previo, fechas, secciones y permisos. Por qué un buen esquema de metadatos vale más que cambiar de modelo.

Metadatos: el ingrediente que más mejora un RAG
Foto de cottonbro studio en Pexels

Quinta entrega del bloque dedicado al corpus. Después de tres artículos sobre cómo cortar el texto, toca lo que se guarda alrededor de cada trozo: la parte menos vistosa de un sistema RAG y, a menudo, la que más diferencia marca entre uno que funciona y uno que casi funciona.

Un fragmento no es sólo texto

En un índice vectorial cada registro tiene un identificador, un vector y el texto del fragmento. Los metadatos son todo lo demás: campos estructurados que se pueden consultar, filtrar y devolver sin pasar por la similitud vectorial.

La razón por la que importan es sencilla: la búsqueda vectorial responde a «¿qué se parece a esto?», y no sabe responder a «¿qué está vigente?», «¿qué puede ver este usuario?» ni «¿de dónde ha salido esto?». Esas preguntas son las que separan un prototipo de un sistema utilizable, y todas se responden con metadatos.

Un fallo típico ilustra el punto. Un usuario pregunta por la política de teletrabajo y el sistema responde con la de 2021, porque aquel documento estaba mejor redactado y se parecía más a la pregunta que el de 2024. La búsqueda funcionó: encontró el texto más parecido. Lo que faltaba no era un modelo mejor, sino un campo de fecha y una regla que lo usara.

Qué guardar

Estos campos acaban haciendo falta en casi cualquier proyecto, y cuesta más añadirlos después que desde el principio.

  • Fuente y procedencia. Identificador, ruta o URL de origen, sistema del que vino. Permite citar, verificar y, llegado el caso, retirar todo lo que venga de una fuente concreta.
  • Fechas. Al menos la del documento y la de indexación. Confundirlas produce errores sutiles: un documento de 2019 ingerido ayer no es reciente.
  • Estructura. Sección, camino de títulos, página, posición del fragmento. Habilita la cita precisa, la expansión a vecinos y el patrón padre-hijo de la entrega 10.
  • Autor o responsable. Para filtrar, atribuir y saber a quién preguntar cuando un documento está mal.
  • Tipo de documento. Contrato, manual, acta, ficha, correo. Es de los filtros más usados y más baratos de asignar, porque casi siempre se deduce del origen.
  • Idioma. Detectado en la ingesta. Permite enrutar, filtrar y detectar extracciones malas.
  • Permisos. Grupos, roles o etiquetas de confidencialidad que determinan quién puede ver el fragmento.
  • Versión y estado. Número de versión, si está vigente o derogado, si sustituye a otro documento. Es lo que evita responder con la política de 2021.
  • Calidad de la extracción. Confianza del OCR, método usado, si el fragmento procede de una tabla. Sirve para depurar y para excluir material dudoso sin borrarlo.

Un esquema de ejemplo

{
  "id": "doc_4471#c012",
  "texto": "El plazo de resolución de incidencias graves se amplía...",

  "fuente": {
    "documento_id": "doc_4471",
    "titulo": "Contrato de mantenimiento - Delegación Norte",
    "uri": "s3://corpus/contratos/2024/mant-norte-v3.pdf",
    "sistema_origen": "gestor_documental",
    "hash_documento": "sha256:9f2c1a…"
  },

  "temporal": {
    "fecha_documento": "2024-03-11",
    "fecha_indexacion": "2024-03-14T09:22:00Z",
    "vigente_desde": "2024-04-01",
    "vigente_hasta": null
  },

  "estructura": {
    "camino_titulos": ["Condiciones del servicio",
                       "Plazos",
                       "Incidencias graves"],
    "pagina": 14,
    "indice_fragmento": 12,
    "total_fragmentos": 47,
    "id_padre": "doc_4471#p003"
  },

  "clasificacion": {
    "tipo": "contrato",
    "area": "operaciones",
    "idioma": "es",
    "autor": "Servicios Jurídicos",
    "etiquetas": ["mantenimiento", "SLA", "delegacion-norte"]
  },

  "control": {
    "version": 3,
    "estado": "vigente",
    "sustituye_a": "doc_4471_v2",
    "permisos": ["grupo:operaciones", "grupo:direccion"],
    "confidencialidad": "interno"
  },

  "extraccion": {
    "metodo": "pdf_nativo",
    "confianza_ocr": null,
    "procede_de_tabla": false
  }
}

Dos observaciones. Está agrupado por bloques por legibilidad, pero muchos motores sólo indexan campos planos, así que en el almacén real conviene aplanarlo a claves como fecha_documento o control_estado. Y los campos que puedan quedar vacíos deben existir igualmente en el esquema: uno que unos documentos tienen y otros no, sin estar declarado, es una fuente inagotable de consultas que devuelven resultados incompletos sin avisar.

Filtrado previo y filtrado posterior

El momento en que se aplica un filtro cambia por completo el resultado. Es una de esas distinciones que parecen un tecnicismo hasta que te muerde.

Filtrado posterior (post-filtering): se busca, se obtienen los k mejores y después se descartan los que no cumplen el filtro. Es trivial de implementar y tiene un defecto grave: si pides diez y ocho no cumplen, te quedas con dos; si ninguno cumple, te quedas sin nada, aunque en el índice hubiera cien fragmentos pertinentes que la búsqueda no llegó a mirar. Empeora cuanto más selectivo es el filtro, que es cuando más falta hace.

Filtrado previo (pre-filtering): se restringen primero los candidatos y se busca por similitud dentro de ese subconjunto, con lo que siempre devuelve k resultados válidos si existen. Es lo que se quiere casi siempre, y no todos los motores lo hacen igual de bien: sobre un índice aproximado como HNSW —el de la entrega 05— no es trivial, porque el grafo se recorre sin saber qué nodos pasan el filtro. Los motores serios filtran durante el recorrido; los que filtran después lo llaman igual y no es lo mismo. Es una pregunta que hay que hacerle a un motor antes de elegirlo.

Hay un caso donde el filtrado previo no es preferencia sino requisito de seguridad: los permisos. Filtrar después significa que el motor ha recuperado y tenido en memoria fragmentos que ese usuario no puede ver, y cualquier traza o mensaje de depuración se convierte en una fuga. Ni siquiera hace falta un fallo: si el número de resultados varía según el usuario, ya se está filtrando información sobre lo que existe. El control de acceso va dentro de la consulta, siempre.

De dónde salen los metadatos

Buena parte se obtiene sin coste, y ahí está el primer sitio donde mirar. Del sistema de origen vienen la ruta, el propietario, las fechas de creación y modificación, los permisos del fichero, la carpeta —que a menudo codifica el área o el cliente— y el nombre; en un gestor documental, además, las etiquetas que alguien ya puso.

De la ingesta vienen el idioma, la estructura, la página, el método de extracción, la confianza del OCR y el hash. Todo eso existe al extraer y desaparece si no se guarda.

Del contenido se extraen campos con reglas: expresiones regulares para referencias, códigos, importes o fechas; listas de términos controlados para clasificar por tema. Es aburrido y funciona bien cuando el dominio tiene formatos estables.

Y queda la extracción con un modelo de lenguaje: pedirle un JSON con tipo, resumen, entidades, temas y fecha de vigencia. Funciona bien, con tres cautelas. Exigir salida estructurada validada contra un esquema y descartar lo que no valide. Acotar los campos categóricos a una lista cerrada: si se deja abierto, el mismo tipo aparecerá como «contrato», «Contrato» y «acuerdo», y filtrar dejará de funcionar. Y hacerlo una vez por documento, heredando los campos a sus fragmentos.

Un apunte de coste que enlaza con la entrega anterior: extraer metadatos es una llamada por documento, mientras que la recuperación contextual era una por fragmento. La diferencia es de un orden de magnitud, y explica por qué esta suele salir a cuenta y la otra hay que pensársela.

Por qué esto rinde más que cambiar de modelo de embeddings

Cuando un sistema RAG no acierta, la reacción habitual es sospechar del modelo de embeddings. A veces es lo correcto. Con más frecuencia de la que se admite, el problema es que la respuesta estaba en el índice y no ganó, por motivos que nada tienen que ver con la calidad de la representación semántica.

Los casos concretos lo dejan claro. Si responde con un documento derogado, falta un campo de estado y una regla que lo use. Si mezcla información de dos clientes, falta un filtro por cliente. Si cita la versión inglesa del mismo manual, falta el campo de idioma. Si un usuario ve algo que no debería, falta el filtrado por permisos. Si la respuesta es correcta pero no se puede verificar, falta la página y el camino de títulos. Ninguno de esos cinco fallos se arregla cambiando de modelo.

Hay además una razón estructural. Cambiar de modelo mueve el ranking unos puntos: los buenos candidatos suben algo y los malos bajan algo. Un filtro por metadatos hace algo cualitativamente distinto: elimina del espacio de búsqueda todo lo que no puede ser la respuesta. Buscar entre 400 fragmentos pertinentes en vez de entre 400.000 mejora la precisión como ningún ajuste de modelo, y además reduce latencia y coste.

Y el coste de cambio no se parece: cambiar de modelo obliga a reindexar el corpus entero y reevaluarlo todo; añadir un campo y un filtro es pequeño y reversible.

Límites y errores frecuentes

También se hacen mal, de tres formas habituales.

La primera es guardar campos que nadie consulta. Cada campo hay que rellenarlo en la ingesta, mantenerlo coherente entre fuentes y actualizarlo cuando el documento cambia. Un esquema de cuarenta campos de los que se usan cinco es peor que uno de ocho bien mantenidos: los otros treinta y cinco acaban desactualizados y alguien acaba fiándose de ellos.

La segunda es la incoherencia entre fuentes: el campo «área» que en un sistema vale «Operaciones» y en otro «OPS» deja fuera media biblioteca. Se resuelve normalizando en la ingesta contra un vocabulario controlado y marcando lo que no encaje, en vez de dejarlo pasar.

La tercera, la más silenciosa: filtrar de más. Un filtro por defecto demasiado estricto —sólo el último año, sólo el área del usuario— deja preguntas legítimas sin respuesta y hace que el sistema diga que no encuentra nada cuando la información estaba ahí. Conviene registrar cuántos candidatos elimina cada filtro: ante una consulta vacía, la primera pregunta es cuántos fragmentos quedaron tras filtrar.

Y un límite honesto: los metadatos son tan fiables como la disciplina con que se mantienen. Un campo de vigencia que nadie actualiza es peor que no tenerlo, porque genera confianza injustificada.

Qué viene ahora

La próxima entrega cierra el bloque con lo que pasa cuando los documentos dejan de ser un lote inicial y se vuelven algo vivo: detección de cambios, reindexación incremental, versionado, duplicados exactos y casi exactos, documentos que se contradicen, caducidad y el borrado real de un índice vectorial.

Los tres libros gratuitos de los que nace esta serie están disponibles en PDF y EPUB: RAG para tu negocio (nivel básico), RAG por dentro (intermedio) y RAG en producción (avanzado).


Aviso de contenido generado con inteligencia artificial.
Este artículo ha sido redactado con la asistencia de sistemas de inteligencia artificial y revisado antes de su publicación. Se informa de ello de forma expresa en cumplimiento de la normativa vigente sobre transparencia en el uso de IA.