Las promesas de la generación de recuperación aumentada (RAG) son que permite a los sistemas de IA responder preguntas utilizando información actualizada o específica de dominio, sin volver a capacitar el modelo. Pero la mayoría de las tuberías de RAG todavía tratan los documentos y la información como planos y desconectados, retrate los trozos aislados basados en la similitud vectorial, sin sentido de cómo se relacionan esos trozos.
Para remediar la ignorancia de Rag de, a menudo obvias, las conectiones entre documentos y trozos, los desarrolladores han recurrido a los enfoques de trapo gráfico, pero a menudo descubrieron que los beneficios del trapo gráfico eran no vale la pena la complejidad adicional de implementarlo.
En nuestro artículo reciente sobre El proyecto de trapo de gráfico de código abierto y grafretrieverintrodujimos un enfoque nuevo y más simple que combina su búsqueda vectorial existente con un recorrido gráfico ligero y basado en metadatos, que no requiere construcción o almacenamiento de gráficos. Las conexiones gráficas se pueden definir en tiempo de ejecución, o incluso en el tiempo de consulta, especificando qué valores de metadatos del documento le gustaría usar para definir “bordes” gráficos, y estas conexiones se atraviesan durante la recuperación en el trapo gráfico.
En este artículo, nos ampliamos uno de los casos de uso en la documentación del proyecto de trapo gráfico:Se puede encontrar un cuaderno de demostración aquí—Cuamente es un ejemplo simple pero ilustrativo: buscar reseñas de películas desde un conjunto de datos Rotten Tomatoes, conectar automáticamente cada revisión con su subgrafio local de información relacionada y luego reunir respuestas de consulta con contexto completo y relaciones entre películas, revisores, revisores y otros atributos de datos y metadatos.
El conjunto de datos: reseñas de Rotten Tomatoes y metadatos de películas
El conjunto de datos utilizado en este estudio de caso proviene de un conjunto de datos de Kaggle público titulado “Películas y reseñas masivas de Rotten Tomatoes”. Incluye dos archivos CSV primarios:
- Rotten_tomatoes_movies.csv: que contiene información estructurada sobre más de 200,000 películas, incluidos campos como título, elenco, directores, géneros, lenguaje, fecha de lanzamiento, tiempo de ejecución y ganancias de taquilla.
- Rotten_tomatoes_movie_reviews.csv: una colección de casi 2 millones de reseñas de películas enviadas por el usuario, con campos como texto de revisión, calificación (p. Ej., 3/5), clasificación de sentimientos, fecha de revisión y referencia a la película asociada.
Cada reseña está vinculada a una película a través de una película_id compartida, creando una relación natural entre el contenido de revisión no estructurado y los metadatos de películas estructurados. Esto lo convierte en un candidato perfecto para demostrar la capacidad de Graxcretriever para atravesar las relaciones de documentos utilizando metadatos solos, sin necesidad de construir ni almacenar manualmente un gráfico separado.
Al tratar los campos de metadatos como Movie_ID, género o incluso actores y directores compartidos como bordes de gráficos, podemos construir un flujo de recuperación conectado que enriquece cada consulta con un contexto relacionado automáticamente.
El desafío: poner reseñas de películas en contexto
Un objetivo común en los sistemas de búsqueda y recomendación de IA es permitir que los usuarios hagan preguntas naturales y abiertas y obtengan resultados significativos y contextuales. Con un gran conjunto de datos de reseñas de películas y metadatos, queremos admitir respuestas de contexto completo a indicaciones como:
- “¿Cuáles son algunas buenas películas familiares?”
- “¿Cuáles son algunas recomendaciones para películas de acción emocionantes?”
- “¿Cuáles son algunas películas clásicas con una cinematografía increíble?”
Una gran respuesta a cada una de estas indicaciones requiere contenido de revisión subjetiva junto con algunos atributos semiestructurados como género, audiencia o estilo visual. Para dar una buena respuesta con contexto completo, el sistema debe:
- Recupere las revisiones más relevantes basadas en la consulta del usuario, utilizando similitud semántica basada en vectores
- Enriquezca cada revisión con detalles completos de la película (títulos, año de lanzamiento, género, director, etc.), por lo que el modelo puede presentar una recomendación completa y fundamentada
- Conecte esta información con otras reseñas o películas que proporcionan un contexto aún más amplio, como: ¿Qué dicen otros revisores? ¿Cómo se comparan otras películas en el género?
Una tubería de trapo tradicional podría manejar bien el paso 1, pulliendo fragmentos de texto relevantes. Pero, sin conocimiento de cómo los fragmentos recuperados se relacionan con otra información en el conjunto de datos, las respuestas del modelo pueden carecer de contexto, profundidad o precisión.
Cómo el trapo gráfico aborda el desafío
Dada la consulta de un usuario, un sistema de trapo simple podría recomendar una película basada en un pequeño conjunto de revisiones directamente semánticamente relevantes. Pero Graph Rag y Graxretriever pueden atraer fácilmente un contexto relevante, por ejemplo, otras reseñas de las mismas películas u otras películas en el mismo género, para comparar y contrastar antes de hacer recomendaciones.
Desde el punto de vista de la implementación, Graph Rag proporciona una solución limpia de dos pasos:
Paso 1: Construya un sistema de trapo estándar
Primero, al igual que con cualquier sistema de RAG, incorporamos el texto del documento utilizando un modelo de idioma y almacenamos los incrustaciones en una base de datos vectorial. Cada revisión incrustada puede incluir metadatos estructurados, como reviseed_movie_id, calificación y sentimiento, información que usaremos para definir relaciones más adelante. Cada descripción de la película incrustada incluye metadatos como Movie_ID, Género, Release_Year, Director, etc.
Esto nos permite manejar la recuperación típica basada en vectores: cuando un usuario ingresa una consulta como “¿Cuáles son algunas buenas películas familiares?”, Podemos obtener reseñas rápidamente del conjunto de datos que están semánticamente relacionados con las películas familiares. Conectarlos con un contexto más amplio ocurre en el siguiente paso.
Paso 2: Agregue el recorrido de gráfico con Graxcretriever
Una vez que las revisiones semánticamente relevantes se recuperan en el Paso 1 utilizando la búsqueda de vectores, podemos usar Gragretriever para atravesar las conexiones entre las revisiones y sus registros de películas relacionados.
Específicamente, el Gragretriever:
- Obtiene reseñas relevantes a través de Semantic Search (RAG)
- Sigue a los bordes basados en metadatos (como reviseed_movie_id) para recuperar más información que esté directamente relacionada con cada revisión, como descripciones y atributos de películas, datos sobre el revisor, etc.
- Fusiona el contenido en una sola ventana de contexto para que el modelo de idioma lo use al generar una respuesta
Un punto clave: no se necesita un gráfico de conocimiento previamente construido. El gráfico se define completamente en términos de metadatos y se atraviesa dinámicamente en el momento de la consulta. Si desea expandir las conexiones para incluir actores, géneros o períodos de tiempo compartidos, solo actualiza las definiciones de borde en la configuración de Retriever, sin necesidad de reprocesar o remodelar los datos.
Entonces, cuando un usuario pregunta sobre películas de acción emocionantes con algunas cualidades específicas, el sistema puede traer puntos de datos como el año de lanzamiento de la película, el género y el elenco, mejorando la relevancia y la legibilidad. Cuando alguien pregunta sobre películas clásicas con una cinematografía increíble, el sistema puede recurrir a reseñas de películas más antiguas y combinarlas con metadatos como género o época, dando respuestas que son subjetivas y basadas en hechos.
En resumen, Graxretriever une la brecha entre las opiniones no estructuradas (texto subjetivo) y el contexto estructurado (metadatos conectados), que producen respuestas de consulta que son más inteligentes, confiables y completas.
GraxrEnver en acción
Para mostrar cómo GraxretRiever puede conectar contenido de revisión no estructurado con metadatos estructurados de películas, caminamos a través de una configuración básica utilizando una muestra del conjunto de datos Rotten Tomatoes. Esto implica tres pasos principales: crear un almacén vectorial, convertir datos sin procesar en documentos Langchain y configurar la estrategia de transversal gráfica.
Ver el cuaderno de ejemplo en el proyecto de trapo gráfico para código completo de trabajo.
Crea la tienda vectorial y las integridades
Comenzamos incrustando y almacenando los documentos, tal como lo haríamos en cualquier sistema de trapo. Aquí, estamos usando Openaiembeddings y la tienda Vector Astra DB:
from langchain_astradb import AstraDBVectorStore
from langchain_openai import OpenAIEmbeddings
COLLECTION = "movie_reviews_rotten_tomatoes"
vectorstore = AstraDBVectorStore(
embedding=OpenAIEmbeddings(),
collection_name=COLLECTION,
)
La estructura de los datos y los metadatos
Almacenamos e incrusimos el contenido de documentos como lo haremos generalmente para cualquier sistema RAG, pero también preservamos metadatos estructurados para su uso en el recorrido gráfico. El contenido del documento se mantiene mínimo (texto de revisión, título de la película, descripción), mientras que los datos estructurados ricos se almacenan en los campos “metadatos” en el objeto de documento almacenado.
Este es el ejemplo JSON de un documento de película en la tienda Vector:
> pprint(documents[0].metadata)
{'audienceScore': '66',
'boxOffice': '$111.3M',
'director': 'Barry Sonnenfeld',
'distributor': 'Paramount Pictures',
'doc_type': 'movie_info',
'genre': 'Comedy',
'movie_id': 'addams_family',
'originalLanguage': 'English',
'rating': '',
'ratingContents': '',
'releaseDateStreaming': '2005-08-18',
'releaseDateTheaters': '1991-11-22',
'runtimeMinutes': '99',
'soundMix': 'Surround, Dolby SR',
'title': 'The Addams Family',
'tomatoMeter': '67.0',
'writer': 'Charles Addams,Caroline Thompson,Larry Wilson'}
Tenga en cuenta que el recorrido gráfico con grafretriever usa solo los atributos de este campo de metadatos, no requiere un gráfico db especializado y no utiliza ninguna llamada de LLM u otras costosas
Configurar y ejecutar grafretriever
El Graphcriever atraviesa un gráfico simple definido por las conexiones de metadatos. En este caso, definimos una ventaja de cada revisión a su película correspondiente utilizando la relación direccional entre revisado_movie_id (en revisiones) y película_id (en descripciones de películas).
Utilizamos una estrategia de recorrido “ansiosa”, que es una de las estrategias de transversal más simples. Ver Documentación para el proyecto Graph Rag Para más detalles sobre estrategias.
from graph_retriever.strategies import Eager
from langchain_graph_retriever import GraphRetriever
retriever = GraphRetriever(
store=vectorstore,
edges=[("reviewed_movie_id", "movie_id")],
strategy=Eager(start_k=10, adjacent_k=10, select_k=100, max_depth=1),
)
En esta configuración:
start_k=10: Recupera 10 documentos de revisión utilizando la búsqueda semánticaadjacent_k=10: Permite que se extraen hasta 10 documentos adyacentes en cada paso del recorrido gráfico.select_k=100: Se pueden devolver hasta 100 documentos totalesmax_depth=1: El gráfico solo se atraviesa un nivel de profundidad, desde una reseña hasta película
Tenga en cuenta que debido a que cada revisión se vincula a una película revisada exactamente, la profundidad transversal del gráfico se habría detenido en 1 independientemente de este parámetro, en este simple ejemplo. Ver Más ejemplos en el proyecto de trapo gráfico para un recorrido más sofisticado.
Invocando una consulta
Ahora puede ejecutar una consulta de lenguaje natural, como:
INITIAL_PROMPT_TEXT = "What are some good family movies?"
query_results = retriever.invoke(INITIAL_PROMPT_TEXT)
Y con un poco de clasificación y reformateo de texto, ver el cuaderno para más detalles, podemos imprimir una lista básica de las películas y reseñas recuperadas, por ejemplo:
Movie Title: The Addams Family
Movie ID: addams_family
Review: A witty family comedy that has enough sly humour to keep adults chuckling throughout.
Movie Title: The Addams Family
Movie ID: the_addams_family_2019
Review: ...The film's simplistic and episodic plot put a major dampener on what could have been a welcome breath of fresh air for family animation.
Movie Title: The Addams Family 2
Movie ID: the_addams_family_2
Review: This serviceable animated sequel focuses on Wednesday's feelings of alienation and benefits from the family's kid-friendly jokes and road trip adventures.
Review: The Addams Family 2 repeats what the first movie accomplished by taking the popular family and turning them into one of the most boringly generic kids films in recent years.
Movie Title: Addams Family Values
Movie ID: addams_family_values
Review: The title is apt. Using those morbidly sensual cartoon characters as pawns, the new movie Addams Family Values launches a witty assault on those with fixed ideas about what constitutes a loving family.
Review: Addams Family Values has its moments -- rather a lot of them, in fact. You knew that just from the title, which is a nice way of turning Charles Addams' family of ghouls, monsters and vampires loose on Dan Quayle.
Luego podemos pasar la salida anterior al LLM para la generación de una respuesta final, utilizando la información completa de las revisiones, así como las películas vinculadas.
Configurar el aviso final y LLM Call se ve así:
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from pprint import pprint
MODEL = ChatOpenAI(model="gpt-4o", temperature=0)
VECTOR_ANSWER_PROMPT = PromptTemplate.from_template("""
A list of Movie Reviews appears below. Please answer the Initial Prompt text
(below) using only the listed Movie Reviews.
Please include all movies that might be helpful to someone looking for movie
recommendations.
Initial Prompt:
{initial_prompt}
Movie Reviews:
{movie_reviews}
""")
formatted_prompt = VECTOR_ANSWER_PROMPT.format(
initial_prompt=INITIAL_PROMPT_TEXT,
movie_reviews=formatted_text,
)
result = MODEL.invoke(formatted_prompt)
print(result.content)
Y, la respuesta final del sistema de trapo gráfico podría verse así:
Based on the reviews provided, "The Addams Family" and "Addams Family Values" are recommended as good family movies. "The Addams Family" is described as a witty family comedy with enough humor to entertain adults, while "Addams Family Values" is noted for its clever take on family dynamics and its entertaining moments.
Tenga en cuenta que esta respuesta final fue el resultado de la búsqueda semántica inicial de revisiones que mencionan películas familiares, además de un contexto ampliado de documentos que están directamente relacionados con estas revisiones. Al expandir la ventana del contexto relevante más allá de la simple búsqueda semántica, el sistema LLM y Graph Graph Rag puede armar respuestas más completas y más útiles.
Pruébalo tú mismo
El estudio de caso en este artículo muestra cómo:
- Mezclar datos no estructurados y estructurados en su tubería de trapo
- Use metadatos como un gráfico de conocimiento dinámico sin construir o almacenar uno
- Mejorar la profundidad y la relevancia de las respuestas generadas por IA mediante la superficie del contexto conectado
En resumen, este es el trapo gráfico en acción: agregar estructura y relaciones para hacer que los LLM no solo recuperen, sino que construyan el contexto y la razón de manera más efectiva. Si ya está almacenando metadatos ricos junto con sus documentos, Graxretriever le ofrece una forma práctica de poner en funcionamiento esos metadatos, sin infraestructura adicional.
Esperamos que esto lo inspire a probar Gragretriever en sus propios datos, todo es de código abierto, especialmente si ya está trabajando con documentos que están implícitamente conectados a través de atributos, enlaces o referencias compartidas.
Puede explorar el cuaderno completo y los detalles de implementación aquí: Graph Rag en reseñas de películas de Rotten Tomatoes.