Vectorización y etiquetado
La calidad de un RAG se decide en buena parte antes de la primera pregunta: en cómo se trocean los documentos, qué información lleva cada fragmento y con qué modelo se calculan sus vectores. Esta página recorre el flujo de ingesta paso a paso.
Archivo → texto → fragmentos (+ contexto) → etiquetas → vectores → base vectorial1. De dónde salen los documentos
| Origen | Componente | Cómo sacar el texto |
|---|---|---|
| Tu almacenamiento de NappAI | Storage Files | Operation Get File con Content Text. Entrega el texto y los datos del archivo (nombre, ruta, tipo, fecha). |
| PDF que llegan al flujo | PDF Extractor | Devuelve el texto ordenado, con títulos y tablas. |
| Google Drive | Drive File Manager | Operation Get con Process File Content activado. |
| Páginas web | URL | Lee el texto de las direcciones que le das. |
Si tus documentos están en el almacenamiento de NappAI, súbelos una vez desde el dashboard (consulta Almacenamiento) y el flujo de ingesta los lee cuando lo ejecutas.
2. Dividir en fragmentos
Un agente no puede leer un manual entero en cada pregunta, y un vector de un documento largo mezcla demasiados temas. Por eso el texto se divide en fragmentos de unos cientos de caracteres. Todos los divisores están en la categoría Text Splitters.
| Divisor | Cómo corta | Cuándo usarlo |
|---|---|---|
| Recursive Character Text Splitter | Por párrafos; si un párrafo es demasiado largo, por líneas y luego por palabras. | La opción por defecto para manuales, políticas y preguntas frecuentes. |
| Contextual Text Splitter | Igual que el anterior (o por frases, con Split Method) y además un modelo añade a cada fragmento una frase de contexto. | Documentos con apartados que no repiten de qué hablan. Ver el punto 3. |
| CharacterTextSplitter | Por un separador fijo que tú eliges. | Textos con una marca clara entre bloques, por ejemplo una línea --- entre fichas. |
| Semantic Text Splitter | Por significado: corta donde cambia el tema, usando un modelo de vectores. | Textos largos sin estructura, como transcripciones. |
| Natural Language Text Splitter | Respetando el final de las frases del idioma que eliges. | Textos corridos en los que no quieres partir frases. |
| Language Recursive Text Splitter | Respetando la estructura de un lenguaje de programación. | Código fuente o documentación técnica con mucho código. |
Tamaño y solapamiento. Chunk Size es el tamaño máximo de cada fragmento y Chunk Overlap el texto que comparten dos fragmentos seguidos, para que una idea cortada por la mitad esté entera en alguno de los dos.
| Configuración | Chunk Size | Chunk Overlap | Resultado |
|---|---|---|---|
| Valores por defecto de los divisores | 1000 | 200 | Un buen punto de partida. |
| Nuestra medición | 800 | 150 | 9 documentos dieron 80 fragmentos de unos 620 caracteres de media. |
| El vídeo de RAG avanzado | 700 | 100 | Fragmentos más cortos para un manual con apartados breves. |
Como orientación: entre 500 y 1000 caracteres, con un solapamiento del 10 al 20 %. Fragmentos más pequeños dan resultados más precisos pero con menos contexto; más grandes, al revés.
3. Añadir contexto a cada fragmento
Muchos fragmentos no dicen de qué hablan. En un manual de cafeteras, el apartado de un error puede empezar por «Este código indica que la sonda no responde» sin nombrar la máquina. Ese fragmento se encuentra mal, y si tres máquinas tienen un error E07, el buscador no sabe cuál es cuál.
Contextual Text Splitter lo resuelve: un modelo lee el documento completo y escribe para cada fragmento una o dos frases que lo sitúan. Por ejemplo:
| Texto | |
|---|---|
| Fragmento | «Este código indica que la sonda de temperatura no responde. Comprueba la resistencia con un polímetro…» |
| Contexto que añade | «Del manual técnico de la cafetera Q90, apartado de códigos de error: el error E07.» |
El fragmento que se guarda lleva el contexto delante (campo text), y además los campos context y chunk por separado, junto con los datos del documento original.
Qué se consigue (medido el 17 de octubre de 2026, 9 documentos y 40 preguntas):
- Con la búsqueda básica, la respuesta correcta aparece entre los cinco primeros resultados en el 93 % de las preguntas, frente al 83 % sin contexto.
- Con contexto, búsqueda híbrida y Local Rerank, la respuesta fue el primer resultado en el 80 % de las preguntas sobre documentos y estuvo entre los cinco primeros en todas (medido de nuevo el 18 de octubre).
Qué cuesta. Una llamada al modelo por fragmento, solo en la ingesta: al preguntar no cuesta nada. Cada llamada envía el documento completo, así que el coste crece con el tamaño de los documentos. En nuestra medición, 80 fragmentos supusieron 80 llamadas y unos 1.800 tokens de entrada por fragmento, y tardaron 23 segundos con 5 peticiones en paralelo (Parallel Requests). Basta un modelo rápido y barato; en el vídeo usamos DeepSeek.
4. Elegir el modelo de vectores
El modelo de vectores (embeddings) convierte cada fragmento y cada pregunta en un vector. Es lo que más influye en la calidad de la búsqueda básica.
| Opción | Componente | Ventajas | A tener en cuenta |
|---|---|---|---|
| Local, en la plataforma | FastEmbed Embeddings (Local) | Sin clave de API, sin coste por uso, tus textos no salen de NappAI. | La primera vez tarda unos segundos en cargar el modelo. |
| Proveedor | OpenAI Embeddings, Cohere, Mistral, Google, Azure OpenAI, Amazon Bedrock… | Modelos de cada proveedor, sin carga inicial. | Necesita su credencial, cuesta por uso y los textos se envían al proveedor. |
| Tu servidor de modelos | Ollama Embeddings | Los modelos que tengas en tu Ollama. | Necesitas tener ese servidor funcionando. |
Lo que medimos con textos en español (resultado: respuesta correcta entre los cinco primeros resultados):
| Modelo | Componente | Acierto | Velocidad por pregunta | Comentario |
|---|---|---|---|---|
jinaai/jina-embeddings-v2-base-es (por defecto) | FastEmbed Embeddings (Local) | 83 % | 10 ms | El mejor equilibrio entre calidad y velocidad. Español e inglés. 768 dimensiones. |
intfloat/multilingual-e5-large | FastEmbed Embeddings (Local) | 87 % | 30 ms | Una pregunta más que el anterior, pero 3 veces más lento por pregunta, 3,5 veces más grande y 2,4 veces más lento al guardar. |
Snowflake/snowflake-arctic-embed-l-v2.0 | FastEmbed Embeddings (Local) | 83 % | 22 ms | El que más veces dejó la respuesta en el primer puesto (70 % frente al 60 % del de por defecto). Tan pesado y lento como el anterior: medidos a la vez, los dos tardaron 22 ms. 1024 dimensiones. |
sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 | FastEmbed Embeddings (Local) | 63 % | 6 ms | El más ligero, pero pensado para comparar frases, no para buscar. |
bge-m3 | Ollama Embeddings | 73–80 % | 20 ms | Correcto, sin mejorar al de por defecto. |
nomic-embed-text | Ollama Embeddings | 53–57 % | 13 ms | Pensado para inglés: encuentra los códigos, pero en preguntas con otras palabras en español falla la mitad. |
En resumen: deja el modelo por defecto de FastEmbed Embeddings (Local) salvo que tengas un motivo, y evita los modelos pensados solo para inglés si tus documentos están en español.
5. Etiquetar los fragmentos
Las etiquetas son datos de cada fragmento (máquina, tema, marca, mes…) por los que luego se puede filtrar la búsqueda. Metadata Tagger las rellena con un modelo que lee cada fragmento.
En Metadata Schema describes los campos con el editor de esquemas: por cada uno, su nombre, su tipo y qué significa. Si un campo solo admite ciertos valores, escríbelos en la descripción. Es el mismo formato que usa SelfQueryRetriever para filtrar, así que puedes copiar el esquema de un componente al otro.
Este es el esquema del vídeo:
| Nombre | Tipo | Descripción |
|---|---|---|
maquina | string | Máquina de la que habla el texto: Q90, DL5, M7, o general si no es de ninguna. |
tema | string | Uno de: averia, mantenimiento, garantia, tarifas, preguntas. |
codigos | array | Códigos de error o alarma que aparecen, como E07 o A2. |
Los tipos posibles son string (texto), integer (número entero), number (número con decimales), boolean (sí o no) y array (una lista de valores).
Opciones útiles: Overwrite Existing Values (desactivado por defecto) conserva el valor que el documento ya traía; Instructions añade indicaciones, por ejemplo cómo escribir los nombres de producto. Coste: una llamada corta por fragmento; en nuestra medición, unos 330 tokens de entrada por fragmento y 15 segundos para 80 fragmentos.
6. Conserva los datos de cada documento
Además de las etiquetas, cada fragmento hereda los datos de su documento: Storage Files aporta el nombre, la ruta y el tipo del archivo, y tanto Contextual Text Splitter como Metadata Tagger los mantienen. Guarda con cada fragmento al menos:
- El origen (nombre del archivo), para que el agente pueda citar de dónde sale la respuesta.
- El tipo de documento (manual, política, informe, preguntas frecuentes).
- La marca o el producto, si tus documentos son de varios.
- El periodo (mes o año), si tienes informes que se repiten con la misma estructura.
Con esos datos a nivel de documento, SelfQueryRetriever acertó el 83 % de las preguntas que necesitaban un filtro, frente al 33 % de la búsqueda sin filtros.
Siguiente paso
Con los fragmentos guardados, elige cómo buscarlos: Técnicas de recuperación.