Implementación de RAG y recuperación de conocimiento en Python
Esta sección introduce la tecnología de Generación Aumentada por Recuperación (Retrieval-Augmented Generation, RAG).
RAG es una de las tecnologías centrales para construir agentes intensivos en conocimiento.
Al combinar la recuperación vectorial con modelos de generación de lenguaje, RAG otorga a los agentes la capacidad de acceder y utilizar conocimiento externo, en lugar de depender únicamente del contenido "memorizado" en los parámetros del modelo.
Principios básicos de RAG
La idea central de RAG es combinar dos etapas, "recuperación de información" y "generación de lenguaje", para formar un flujo completo de preguntas y respuestas.
Cuando el usuario plantea una pregunta, el sistema primero recupera de la base de conocimiento los contenidos relacionados con la pregunta.
Luego, el sistema proporciona el contenido recuperado como contexto al modelo de generación, ayudándolo a producir respuestas más precisas y fundamentadas.
Por qué se necesita RAG
Los modelos de lenguaje tienen una fecha límite de conocimiento y no pueden percibir eventos posteriores a su entrenamiento.
Los parámetros del modelo son limitados; es imposible almacenar todo el conocimiento del mundo en ellos.
Si se depende completamente de que el modelo "recuerde" conocimiento desde sus parámetros, cuando encuentra contenido que no recuerda con precisión o que nunca aprendió, tiende a inventar respuestas con total seriedad; esto es lo que se conoce como "alucinación" (hallucination).
El enfoque de RAG consiste en hacer que el modelo consulte fuentes reales antes de responder, convirtiendo "responder de memoria" en "responder con el material abierto". Las fuentes de conocimiento también pueden actualizarse en cualquier momento sin necesidad de reentrenar el modelo.
Arquitectura central
Un sistema RAG completo generalmente incluye tres componentes centrales:
Recuperador (Retriever): Se encarga de encontrar en la base de conocimiento los fragmentos de información más relevantes para la pregunta.
Base de datos vectorial (Vector Store): almacena las representaciones vectoriales correspondientes al contenido de los documentos y admite búsqueda de similitud a gran escala y de baja latencia.
Generador (Generator): genera la respuesta final en lenguaje natural basándose en el contenido recuperado y la pregunta original del usuario.
La relación entre los tres puede entenderse así: el recuperador se encarga de "buscar información", la base de datos vectorial de "almacenar información y encontrar rápidamente información similar", y el generador de "organizar la respuesta a partir de la información".
Flujo de trabajo
Primer paso,Etapa de indexación. Se divide el documento original en varios fragmentos de texto (chunks), se vectorizan uno a uno y se almacenan en la base de datos vectorial; este paso suele realizarse de forma offline y anticipada.
Segundo paso,Etapa de recuperación. Cuando el usuario realiza una consulta, la consulta se vectoriza de la misma manera y se realiza una búsqueda por similitud en la base de datos vectorial para encontrar los bloques de texto más relevantes.
Tercer paso,Etapa de aumento. Los bloques de texto relevantes recuperados se combinan con la pregunta original del usuario para construir un prompt más completo.
Cuarto paso,Etapa de generación. El modelo de generación produce la respuesta final basándose en este contexto enriquecido.
De estos cuatro pasos, solo el primero es un preprocesamiento offline; los otros tres ocurren en tiempo real cuando el usuario pregunta. Por lo tanto, la velocidad y la calidad de la recuperación determinan directamente la velocidad de respuesta y la calidad de las respuestas de todo el sistema.
Implementación de código
Implementación básica de RAG
"""
Implementación del sistema RAG simplificado
Incluye tres componentes centrales: embedder, almacenamiento vectorial y generador.
"""
def __init__(self, embedder, vector_store, generator):
# Embedder: se encarga de convertir el texto en vectores
self.embedder = embedder
# Base de datos de vectores: se encarga de almacenar vectores y soporta la búsqueda por similitud
self.vector_store = vector_store
# Generador: genera respuestas basándose en el contexto
self.generator = generator
def add_documents(self, documents):
"""
Agregar el documento a la base de conocimiento
:param documents: lista de documentos originales (cada elemento es un fragmento de texto completo)
"""
# Primer paso: dividir el documento largo en fragmentos de texto más pequeños para facilitar la recuperación precisa
chunks = self.chunk_documents(documents)
# Paso 2: Convertir todos los fragmentos de texto en vectores
embeddings = self.embedder.embed(chunks)
# Paso 3: guardar el vector junto con el texto original correspondiente en la base de datos vectorial
self.vector_store.add(embeddings, chunks)
def chunk_documents(self, documents, chunk_size=500, overlap=50):
"""
Segmentación de documentos: dividir documentos largos en bloques de texto de longitud fija con cierta superposición
:param documents: lista de documentos originales
:param chunk_size: Número de caracteres de cada bloque de texto.
:param overlap: cantidad de caracteres superpuestos entre bloques de texto adyacentes (para evitar que la semántica se trunque en el punto de corte).
:return: lista de bloques de texto segmentados
"""
chunks = []
for doc in documents:
# Segmentar deslizando con tamaño de paso (chunk_size - overlap), manteniendo cierta superposición
for i in range(0, len(doc), chunk_size - overlap):
chunk = doc[i:i + chunk_size]
chunks.append(chunk)
return chunks
def query(self, question, top_k=5):
"""
Procesar la consulta del usuario y devolver la respuesta generada
:param question: pregunta formulada por el usuario
:param top_k: Número de bloques de texto relevantes devueltos durante la recuperación
:return: la respuesta final generada por el modelo
"""
# 1. Convierte la consulta en un vector para poder compararla con los vectores de la base de conocimiento
question_embedding = self.embedder.embed([question])[0]
# 2. Recuperar los bloques de texto top_k más similares en la base de datos vectorial
results = self.vector_store.search(question_embedding, top_k)
# 3. Concatenar los bloques de texto recuperados para formar el contexto
context = "\n".join([doc for doc, _ in results])
# 4. Organizar el contexto y la pregunta original juntos en un prompt
prompt = f"Responda a la pregunta basándose en el siguiente contenido:\n{context}\n\nPregunta: {question}"
# 5. Pasar al modelo generativo para producir la respuesta final
return self.generator.generate(prompt)
Esta implementación básica ya puede ejecutar un flujo RAG completo, pero en proyectos reales suele ser insuficiente: el método de división es demasiado simple y brusco, y la clasificación de la recuperación depende solo de un cálculo de similitud vectorial, con precisión limitada. A continuación se presentan varias estrategias de optimización comunes.
Advanced RAG
Los problemas comunes del RAG básico incluyen: la baja calidad del contenido recuperado, una clasificación insuficientemente precisa y la mezcla de información irrelevante en el contexto.
Advanced RAG optimiza aún más el flujo básico mediante la introducción de técnicas como el reordenamiento y la recuperación híbrida, mejorando así la precisión de las respuestas finales.
Reordenamiento (Reranking)
La recuperación vectorial de RAG básico es rápida, pero la precisión de la clasificación es limitada y tiende a colocar en los primeros puestos contenido que no es lo suficientemente relevante a nivel semántico.
El enfoque de reranking consiste en: primero usar la búsqueda vectorial para filtrar rápidamente un conjunto de textos candidatos (por ejemplo, top-20), y luego usar un Cross-Encoder, que requiere más computación pero es más preciso, para puntuar cada candidato, reordenarlos y seleccionar los pocos realmente más relevantes (por ejemplo, top-5).
Este enfoque de dos etapas, "primero filtrar de forma aproximada y luego refinar la clasificación", equilibra la velocidad de recuperación y la precisión de la recuperación.
RAG con reranking
"""
Sistema RAG avanzado
Agregar una etapa de reordenamiento al flujo básico
"""
def __init__(self, embedder, vector_store, reranker, generator):
# Embedder
self.embedder = embedder
Base de datos vectorial
self.vector_store = vector_store
# Modelo de reordenamiento (cross-encoder), para clasificación refinada
self.reranker = reranker
# Generador
self.generator = generator
def query(self, question, initial_k=20, final_k=5):
"""
Procesa la consulta, incluyendo una recuperación en dos etapas de "filtrado grueso + clasificación fina".
:param question: pregunta del usuario
:param initial_k: número de candidatos devueltos por la búsqueda vectorial en la primera etapa
:param final_k: cantidad final retenida después del reordenamiento
"""
# ==================== Etapa 1: Búsqueda preliminar (cribado grueso) ====================
# Convertir la pregunta en vector
question_embedding = self.embedder.embed([question])[0]
# Usar similitud vectorial para recuperar rápidamente un lote de textos candidatos (rápido, precisión media)
initial_results = self.vector_store.search(
question_embedding,
initial_k
)
# ==================== Fase 2: Reordenamiento (Preciso) ====================
# Construir pares (pregunta, documento candidato) y pasarlos al codificador cruzado para puntuar uno por uno.
doc_pairs = [(question, doc) for doc, _ in initial_results]
# El codificador cruzado codifica la pregunta y el documento simultáneamente, lo que permite juzgar con mayor precisión la relevancia entre ambos
reranked = self.reranker.rerank(doc_pairs)
# Obtener los final_k realmente más relevantes después del reordenamiento.
final_context = "\n".join([doc for doc, _ in reranked[:final_k]])
# ==================== Etapa 3: Generación ====================
prompt = fContexto: {final_context}\n\nPregunta: {question}"
return self.generator.generate(prompt)
Recuperación híbrida
La recuperación híbrida (Hybrid Retrieval) combina las ventajas de la recuperación densa y la recuperación dispersa.
La recuperación densa (Dense Retrieval) se basa en la similitud vectorial y es buena para capturar la relevancia semántica; incluso si la pregunta del usuario y el documento no usan exactamente las mismas palabras, puede haber coincidencia.
La recuperación dispersa (como BM25) se basa en estadísticas de frecuencia de términos de palabras clave, destaca en la coincidencia literal precisa y, en escenarios como nombres propios, números y fragmentos de código, suele ser más fiable que la recuperación vectorial.
Cada uno tiene sus puntos ciegos: la búsqueda vectorial puede "entender el significado pero no encontrar las palabras clave exactas", mientras que la búsqueda por palabras clave puede "coincidir las palabras pero no entender la semántica". La búsqueda híbrida fusiona los resultados de ambas rutas de recuperación para complementarse mutuamente.
RAG con búsqueda híbrida
"""
Recuperación híbrida RAG
Combinar la recuperación densa (vectorial) y la recuperación dispersa (por palabras clave)
"""
def __init__(self, dense_retriever, sparse_retriever, fusion_fn):
# Recuperador denso: basado en similitud de vectores, experto en coincidencia semántica
self.dense_retriever = dense_retriever
# Recuperador disperso: basado en estadísticas de palabras clave (como BM25), bueno para coincidencias exactas.
self.sparse_retriever = sparse_retriever
# Función de fusión: se utiliza para combinar los resultados de dos rutas de recuperación, por ejemplo RRF (ver implementación a continuación)
self.fusion_fn = fusion_fn
def query(self, question, top_k):
"""
Ejecutar la búsqueda híbrida y devolver los resultados tras la fusión de rankings
:param question: pregunta del usuario
:param top_k: la cantidad de resultados que se devuelven al final.
"""
# ==================== Recuperación densa ====================
# Recuperar más candidatos (top_k * 2), dejando espacio para filtrar durante la fusión
dense_results = self.dense_retriever.search(question, top_k * 2)
# ==================== Recuperación dispersa ====================
# Búsqueda basada en palabras clave, también recuperar más candidatos
sparse_results = self.sparse_retriever.search(question, top_k * 2)
# ==================== Fusión de resultados ====================
# Usar estrategias como Reciprocal Rank Fusion (RRF) para fusionar los resultados de dos clasificaciones
fused = self.fusion_fn(dense_results, sparse_results)
# Obtener los top_k elementos mejor clasificados después de la fusión
return fused[:top_k]
def reciprocal_rank_fusion(results_a, results_b, k=60):
"""
Algoritmo Reciprocal Rank Fusion (RRF)
Se utiliza para fusionar los resultados de clasificación de dos (o más) vías de recuperación en una clasificación unificada
Idea central: solo observar el "ranking" de cada documento en los resultados de cada vía, no la puntuación específica,
Evita el problema de que las puntuaciones de similitud vectorial y las puntuaciones BM25 difieren en escala y no se pueden comparar directamente.
:param results_a: Resultados de búsqueda A, formato [(doc, score), ...]
:param results_b: Resultados de búsqueda B, formato [(doc, score), ...]
:param k: constante de suavizado, utilizada para reducir las diferencias de peso entre los documentos con menor ranking; normalmente se toma 60.
:return: Lista de [(doc, score), ...] ordenada por puntuación de fusión de mayor a menor
"""
scores = {}
# Resultado de procesamiento A: cuanto más alto sea el puesto, mayor será la puntuación contribuida
for rank, (doc, _) in enumerate(results_a):
scores[doc] = scores.get(doc, 0) + 1 / (k + rank + 1)
# Procesar el resultado B, acumulando también las puntuaciones según el ranking
for rank, (doc, _) in enumerate(results_b):
scores[doc] = scores.get(doc, 0) + 1 / (k + rank + 1)
# Ordenar de mayor a menor por las puntuaciones de fusión acumuladas
sorted_docs = sorted(scores.items(), key=lambda x: -x[1])
return sorted_docs
Otras estrategias de optimización
Expansión de consultas: Expande la consulta original añadiendo sinónimos o palabras relacionadas, ampliando el alcance de recuperación y mejorando la tasa de recall.
Reescritura de consultas: utiliza modelos para comprender la intención real del usuario y reescribe preguntas coloquiales o ambiguas en formulaciones más adecuadas para la recuperación.
Compresión de contexto: Antes de entregar los resultados de recuperación al modelo generativo, se eliminan las partes redundantes e irrelevantes y se conserva solo la información clave, lo que reduce costos y el riesgo de que el modelo generativo se vea interferido por contenido no relacionado.
Base de datos vectorial
La base de datos vectorial es la infraestructura del sistema RAG; se encarga de almacenar enormes cantidades de vectores de alta dimensión y admite búsqueda de similitud a gran escala y de baja latencia.
Conceptos clave
Incrustación (Embedding): el proceso de convertir texto (o imágenes, audio, etc.) en un conjunto de vectores numéricos densos; el contenido semánticamente similar queda más cerca en el espacio vectorial.
Dimensión vectorial: la longitud del vector de incrustación. Cuanto mayor es la dimensión, en teoría más rica es la información semántica que puede expresarse, pero también aumentan los costos de almacenamiento y cómputo.
Medida de similitud: métodos de cálculo específicos para medir el "grado de similitud" o la "distancia" entre dos vectores; diferentes métricas son adecuadas para diferentes escenarios.
Medidas de similitud comunes
| Método de medición | fórmula | característica | Escenarios de aplicación |
|---|---|---|---|
| Similitud coseno | cos(A,B) = A·B/(|A||B|) | Solo mide la similitud direccional, independientemente de la magnitud del vector; rango de valores [-1,1]. | Similitud de documentos/texto |
| Distancia euclidiana | d(A,B) = sqrt(sum((Ai-Bi)^2)) | Mide la distancia espacial absoluta entre vectores; rango de valores [0,+∞). | Coincidencia de características de imagen |
| producto escalar | A·B = sum(Ai*Bi) | Se ve afectada tanto por la dirección como por la magnitud; alta eficiencia computacional. | Sistema de recomendación |
Comparación de las principales bases de datos vectoriales
| base de datos | Tipo | característica | Escenarios de aplicación |
|---|---|---|---|
| Pinecone | servicio en la nube | Servicio totalmente gestionado, fácil de usar, escalado automático, sin necesidad de operación y mantenimiento propios. | Entornos de producción que necesitan un lanzamiento rápido |
| Weaviate | código abierto | Soporte nativo para recuperación híbrida (vectores + palabras clave), alto grado de modularización. | Escenarios que requieren una lógica de recuperación personalizable y flexible |
| Milvus | código abierto | Alta disponibilidad, fácil escalado horizontal, capaz de soportar escalas de miles de millones de vectores o más. | Recuperación vectorial a muy gran escala |
| Chroma | código abierto | Ligero, API simple, se puede poner en marcha con unas pocas líneas de código. | Desarrollo de prototipos, enseñanza y pruebas locales |
| Qdrant | código abierto | Implementado en Rust, excelente rendimiento, admite abundantes condiciones de filtrado. | Escenarios que requieren alto rendimiento y filtrado complejo |
Ejemplo de código
Usando la base de datos vectorial Chroma.
from chroma_client import ChromaClient
# Crear el cliente (puede conectarse a una instancia local o a un servicio remoto)
client = ChromaClient()
# Crear u obtener una colección (Collection), equivalente a una "tabla" en bases de datos relacionales.
collection = client.get_or_create_collection("knowledge_base")
# Añadir documento: ID, vector, texto original, metadatos deben corresponder uno a uno
collection.add(
ids=["doc1", "doc2", "doc3"], # Identificador único de cada documento
embeddings=[
[0.1, 0.2, 0.3], # El vector correspondiente al documento 1 (la dimensión real suele ser mucho mayor que 3).
[0.4, 0.5, 0.6], # Vector correspondiente al documento 2
[0.7, 0.8, 0.9], # Vector correspondiente al documento 3
],
documents=[
"La inteligencia artificial es una rama de la informática",
El aprendizaje automático es un subcampo de la inteligencia artificial,
El aprendizaje profundo es un subcampo del aprendizaje automático
],
metadatas=[
{"source": "libro de texto"}, # Información de origen del documento 1, utilizable para filtrar posteriormente
{"source": "Artículo"},
{"source": "Artículo"}
]
)
# Recuperación: ingresa el vector de consulta y devuelve los n_results resultados más similares
results = collection.query(
query_embeddings=[[0.15, 0.25, 0.35]], # Vector correspondiente a la consulta
n_results=2 # Devolver los top-2 resultados más similares
)
# Mostrar resultados de recuperación
print(results["documents"]) # Contenido original coincidente
print(results["distances"]) # La puntuación de distancia/similitud correspondiente: cuanto menor sea el valor, normalmente más similar
Al elegir una base de datos vectorial, es necesario considerar de manera integral el volumen de datos, los requisitos de latencia de consulta, el método de implementación (nube gestionada o autogestionada) y la capacidad de operación y mantenimiento del equipo. Para desarrollo de prototipos a pequeña escala, se prefiere Chroma; para entornos de producción listos para usar, se puede elegir Pinecone; para escenarios a muy gran escala que requieren control autónomo, Milvus o Qdrant son más adecuados.
GraphRAG
GraphRAG es una solución avanzada que combina el Grafo de Conocimiento (Knowledge Graph) con RAG.
Mejora las capacidades de recuperación y razonamiento del sistema mediante la construcción de una estructura de grafo compuesta por entidades y relaciones.
Por qué se necesita GraphRAG
El RAG tradicional se basa en la búsqueda de similitud de fragmentos de texto y tiene dificultades para manejar problemas que requieren "razonamiento de múltiples saltos" (es decir, respuestas que requieren encadenar múltiples piezas de información).
El RAG tradicional tampoco captura fácilmente de manera explícita las relaciones semánticas entre entidades, como información estructurada del tipo "quién es el superior de quién" o "qué empresa adquirió a qué empresa".
GraphRAG organiza explícitamente estas entidades y relaciones en una estructura de grafo, permitiendo que el sistema razone a lo largo de rutas de relación, en lugar de solo "buscar textos similares".
Ventajas principales
Capaz de capturar relaciones semánticas entre entidades y formar una red de conocimiento estructurada, no solo fragmentos de texto dispersos.
Admite razonamiento basado en rutas y puede responder mejor a preguntas relacionales.
Puede manejar problemas complejos que requieren razonamiento de múltiples saltos (multi-hop), como "¿quién es el mentor del mentor de alguien?", que necesitan atravesar varios nodos de relación consecutivamente para llegar a la respuesta.
Implementación de código
Implementación de GraphRAG
"""
Sistema GraphRAG
Combina la recuperación mediante grafos de conocimiento y la recuperación vectorial, atendiendo tanto al razonamiento relacional como a la similitud semántica
"""
def __init__(self, kg_builder, embedder, vector_store, generator):
# Constructor de grafo de conocimiento: responsable de extracción de entidades/relaciones y consulta del grafo
self.kg_builder = kg_builder
# Embedder: se utiliza para convertir documentos y preguntas en vectores.
self.embedder = embedder
# Base de datos vectorial: como canal complementario para la recuperación del grafo de conocimiento
self.vector_store = vector_store
# Generador: genera la respuesta final basada en el contexto fusionado
self.generator = generator
def index_documents(self, documents):
"""
Indexar el documento simultáneamente en el grafo de conocimiento y la base de datos vectorial
:param documents: lista de documentos
"""
for doc in documents:
# Extraer entidades del documento
# Por ejemplo, extraer de "OpenAI fue fundada en 2015"
# Entidad: OpenAI (organización), 2015 (tiempo)
entities = self.kg_builder.extract_entities(doc)
# Extraer las relaciones entre entidades de los documentos
# Por ejemplo, extraer el triplete de relación: (OpenAI, fundado en, 2015)
relations = self.kg_builder.extract_relations(doc)
# Escribir las entidades y relaciones en el grafo de conocimiento
self.kg_builder.add_entities(entities)
self.kg_builder.add_relations(relations)
# También vectoriza el texto original y lo almacena en la base de datos vectorial para complementar la búsqueda semántica
embedding = self.embedder.embed([doc])
self.vector_store.add(embedding, [doc])
def query(self, question):
"""
Procesamiento de consultas: combinación de razonamiento de grafos de conocimiento y recuperación vectorial
"""
# ==================== Recuperación de Grafo de Conocimiento ====================
# Primero identifica las entidades relevantes involucradas en el problema
# Por ejemplo, "¿Quién fundó OpenAI?" -> identificar la entidad "OpenAI"
relevant_entities = self.kg_builder.query_entities(question)
# Basándose en estas entidades, extraer del grafo el subgrafo directamente relacionado con ellas.
# El subgrafo contiene entidades relevantes y sus nodos adyacentes, aristas de conexión
subgraph = self.kg_builder.get_subgraph(relevant_entities)
# ==================== Búsqueda vectorial ====================
# Como canal complementario, recuperar contenido textual semánticamente similar
vector_results = self.vector_store.search(question, top_k=5)
# ==================== Fusión de resultados ====================
# Fusionar los resultados del razonamiento del grafo con los resultados de búsqueda vectorial en un contexto unificado
combined_context = self.fuse_results(subgraph, vector_results)
# ==================== Generar ====================
return self.generator.generate(combined_context, question)
def fuse_results(self, subgraph, vector_results):
"""
Fusionar el subgrafo del grafo de conocimiento con los resultados de la búsqueda vectorial y organizarlos en un texto de contexto legible por el modelo generativo.
"""
# Convierte el subgrafo en una descripción en lenguaje natural (por ejemplo, "OpenAI - fundada en -> 2015")
kg_text = subgraph.to_text()
# Concatenar los fragmentos de texto original recuperados por búsqueda vectorial
vector_text = "\n".join([doc for doc, _ in vector_results])
return f"{kg_text}\n{vector_text}"
class KnowledgeGraphBuilder:
Constructor de grafos de conocimiento (implementación ilustrativa; en proyectos reales se suelen invocar modelos especializados de NER/extracción de relaciones)
def extract_entities(self, text):
"""
Extraer entidades nombradas del texto, normalmente mediante un modelo de NER (Reconocimiento de Entidades Nombradas).
Los tipos de entidad comunes incluyen PERSON (persona), ORG (organización), TIME (tiempo), etc.
"""
entities = []
return entities
def extract_relations(self, text):
"""
Extraer las relaciones entre entidades del texto, generalmente se realiza mediante un modelo de extracción de relaciones (Relation Extraction)
Las relaciones generalmente se representan como tripletas: (entidad cabeza, tipo de relación, entidad cola)
"""
relations = []
return relations
def query_entities(self, question):
Según la pregunta del usuario, identificar las entidades involucradas en la pregunta para la posterior recuperación de subgrafos
return []
Escenarios de aplicación
GraphRAG es especialmente adecuado para los siguientes escenarios:
Preguntas y respuestas que requieren comprender relaciones entre entidades, por ejemplo, "¿quién es el CEO de esta empresa?".
Problemas que requieren razonamiento de múltiples saltos para obtener la respuesta, por ejemplo, "¿quién es el mentor del mentor de Zhang San?".
Escenarios donde es necesario descubrir relaciones implícitas en la base de conocimiento que no están escritas explícitamente.
Es importante tener en cuenta que la construcción y el mantenimiento de un grafo de conocimiento conlleva ciertos costos de ingeniería (precisión de la extracción de entidades/relaciones, actualización y mantenimiento del grafo, etc.), por lo que es más adecuado para escenarios con requisitos claros de razonamiento relacional, y no se recomienda como punto de partida predeterminado para todos los proyectos RAG.
Comparación de soluciones y recomendaciones de selección
| solución | Idea central | ventaja | limitación | Escenarios de aplicación |
|---|---|---|---|---|
| RAG básico | Búsqueda vectorial + generación directa | Implementación simple, bajo costo y curva de aprendizaje rápida | Precisión de recuperación limitada; es fácil recuperar contenido no suficientemente relevante | Preguntas y respuestas simples, validación rápida de prototipos |
| Advanced RAG (reordenamiento) | Filtrado grueso vectorial + reranking con Cross-Encoder | Mejora significativamente la precisión del ordenamiento de la recuperación | Añade una inferencia adicional del modelo, aumentando la latencia y el costo. | Escenarios con altos requisitos de precisión en las respuestas |
| Recuperación híbrida | Fusión de búsqueda vectorial y búsqueda por palabras clave | Equilibra la coincidencia semántica y la coincidencia exacta de palabras clave | Requiere mantener dos índices de recuperación simultáneamente | Bases de conocimiento con abundantes nombres propios, código y números. |
| GraphRAG | Fusión de grafo de conocimiento y búsqueda vectorial | Admite razonamiento relacional y preguntas y respuestas multi-salto | El costo de construcción y mantenimiento del grafo es alto | Escenarios con requisitos claros de razonamiento relacional y de múltiples saltos. |
Resumen del capítulo
Este capítulo presenta las tecnologías centrales de RAG y la recuperación de conocimiento.
Principios básicos de RAG: al combinar la recuperación y la generación, permite que los agentes respondan preguntas utilizando conocimiento externo, en lugar de depender por completo de la memoria de los parámetros del modelo.
Advanced RAG: mediante técnicas como el reordenamiento y la recuperación híbrida, mejora aún más la calidad de la recuperación y la precisión de las respuestas sobre el flujo básico.
Base de datos vectorial: es la infraestructura del sistema RAG, responsable de almacenar y recuperar eficientemente las representaciones vectoriales de los documentos; la selección debe evaluarse de manera integral según el volumen de datos y el método de implementación.
GraphRAG: al integrar grafos de conocimiento, refuerza el razonamiento relacional y la capacidad de preguntas y respuestas de múltiples saltos, pero también conlleva costos adicionales de construcción y mantenimiento.
Para elegir la solución RAG adecuada, lo clave es comprender primero las necesidades reales del escenario de negocio: para preguntas y respuestas simples, el RAG básico suele ser suficiente; si se requieren alta precisión en la recuperación, se puede introducir el reordenamiento; si la base de conocimiento tiene muchos nombres propios/palabras clave, es adecuado incorporar recuperación híbrida; si involucra mucho razonamiento relacional y preguntas y respuestas de múltiples saltos, entonces considerar GraphRAG. Cuanto más compleja es la tecnología, mayores son los costos de ingeniería y mantenimiento; elegir según la necesidad es más importante que perseguir ciegamente "soluciones más avanzadas".
Otras extensiones