Los modelos de lenguaje de gran tamaño (LLM) son increíblemente potentes, pero su conocimiento se limita a sus conjuntos de datos de entrenamiento. Al responder preguntas, especialmente sobre información específica, en evolución o patentada, los LLM pueden alucinar o proporcionar respuestas generales e irrelevantes. La generación aumentada por recuperación (RAG) ayuda al proporcionar al LLM información recuperada relevante de fuentes de datos externas.
Sin embargo, no todas las RAG son iguales. La generación aumentada por recuperación correctiva (cRAG) no se basa simplemente en la RAG más tradicional, sino que representa una mejora significativa. Está diseñada para ser más robusta al evaluar la calidad y la relevancia de los resultados recuperados. Si el contexto es débil, irrelevante o procede de una fuente poco fiable, la cRAG intenta encontrar mejor información mediante acciones correctivas o se niega explícitamente a responder en lugar de fabricar una respuesta. Esta técnica hace que los sistemas de cRAG sean más fiables y dignos de confianza para aplicaciones críticas, como responder a preguntas relacionadas con políticas.
En este tutorial, aprenderá a crear un sistema robusto de RAG correctiva (cRAG) con modelos de IBM® Granite en Watsonx y LangChain. También se pueden utilizar marcos similares como LlamaIndex o LangGraph para crear flujos de RAG complejos con nodos distintos. Técnicas como el ajuste fino pueden mejorar aún más el rendimiento del LLM específico para la RAG de un dominio específico. Los LLM como los de OpenAI (por ejemplo, modelos GPT como ChatGPT) también son opciones populares para dichos agentes, aunque este tutorial se centra en IBM Granite.
Aquí nos centraremos en un caso de uso: responder a preguntas sobre un documento específico de una póliza de seguros (un PDF). Este tutorial le guiará en la implementación de un sofisticado algoritmo de RAG que:
Recupera información de su propio documento PDF.
Si los documentos internos no son suficientes para generar la respuesta, el agente puede utilizar una búsqueda web externa (Tavily) como alternativa.
El agente filtra de forma inteligente los resultados externos irrelevantes para que las respuestas se adapten a las políticas privadas.
El agente dará respuestas claras y limitadas con información parcial cuando esté disponible o una negativa clara cuando falte contexto.
Este tutorial es una demostración de la creación de un agente de consulta de pólizas de seguros diseñado para analizar documentos de pólizas (un folleto en PDF) y responder con precisión a las consultas de los usuarios. Utilizamos los modelos IBM Granite y LangChain para crear el agente con pasos robustos de recuperación y verificación que garanticen respuestas de alta calidad y limitadas por la fuente.
Entendamos cómo se aplican los principios clave de una RAG fiable en nuestro caso de uso.
Base de conocimientos interna (PDF): la principal fuente de información del agente es el PDF de su póliza de seguro. Convierte este documento en un almacén de vectores en el que se pueden realizar búsquedas.
Búsqueda externa alternativa (Tavily): si la base de conocimientos interna no tiene suficiente información, el agente puede consultar fuentes web externas a través de Tavily. Tavily es un motor de búsqueda creado específicamente para agentes de IA y LLM que permite una recuperación más rápida y en tiempo real a través de su interfaz de programación de aplicaciones (API) para aplicaciones basadas en RAG.
Puntuación contextual: el evaluador de recuperación basado en LLM (que actúa como calificador) proporcionará una puntuación a la relevancia de los elementos recuperados de su PDF interno a la vez que garantiza que solo se incluyan los elementos recuperados de alta calidad.
Reescritura de consultas: para las búsquedas web, el agente puede reformular la consulta del usuario para mejorar las posibilidades de encontrar información externa relevante.
Verificación de la fuente: una comprobación impulsada por LLM evalúa si los resultados de búsqueda web externos son relevantes para una póliza de seguro privado, filtrando información general o detalles sobre programas de salud pública (como Medi-Cal). Esta función evita la generación de respuestas engañosas y permite la autocorrección, lo que ayuda a refinar el conocimiento.
Generación restringida: la instrucción final del LLM le indica estrictamente que utilice solo el contexto proporcionado, ofrezca respuestas exactas, indique cuándo la información no está disponible o proporcione respuestas parciales con limitaciones explícitas. Esta función mejora la adaptabilidad y la fiabilidad de las respuestas generadas.
Necesita una cuenta de IBM® Cloud para crear un proyecto watsonx.ai . Asegúrese de tener acceso tanto a su clave API watsonx como a su ID de proyecto. También necesitará una clave API para Tavily IA para las capacidades de búsqueda web.
Aunque puede elegir entre varias herramientas, este tutorial le muestra cómo configurar una cuenta de IBM con un Jupyter Notebook.
Este paso abre un entorno de notebook donde puede copiar el código de este tutorial. También puede descargar este notebook en su sistema local y cargarlo en su proyecto de watsonx.ai como un activo. Para ver más tutoriales de Granite, consulte la comunidad de IBM® Granite. Este tutorial también está disponible en GitHub.
Para trabajar con el marco LangChain e integrar el LLM de IBM® watsonx, necesitamos instalar algunas bibliotecas esenciales. Comencemos instalando los paquetes necesarios: Este conjunto incluye langchain para el marco RAG, langchain-ibm para la integración de watsonx, faiss-cpu para un almacenamiento vectorial eficiente, PyPDF2 para procesar archivos PDF, sentence-transformers para obtener un embedding y requests para las llamadas a la API web. Estas bibliotecas son críticas para aplicar soluciones de machine learning y PLN.
Nota: no se requiere GPU, pero la ejecución puede ser más lenta en sistemas basados en CPU. Este paso abre un entorno de notebook donde puede copiar el código de este tutorial. Este tutorial también está disponible en GitHub.
A continuación, importe todos los módulos necesarios y proporcione de forma segura sus claves API para watsonx y Tavily, junto con su ID de proyecto de watsonx.
os ayuda a trabajar con el sistema operativo.
io permite trabajar con flujos de datos.
getpass utiliza una forma segura de capturar información confidencial, como claves API, y no muestra la entrada en la pantalla.
PyPDF2.PdfReader permite la extracción de contenido de archivos PDF.
langchain_ibm.WatsonxLLM nos permite utilizar el LLM de IBM® Watsonx Granite fácilmente dentro del marco LangChain.
langchain.embeddings.HuggingFaceEmbeddings toma un modelo HuggingFace y genera los embeddings textuales que son importantes para la búsqueda semántica.
langchain.vectorstores.FAISS es una biblioteca para el almacenamiento eficiente de vectores y la búsqueda de similitudes que nos permite crear un índice vectorial y consultarlo.
langchain.text_splitter.RecursiveCharacterTextSplitter ayuda a dividir grandes componentes de texto en los fragmentos más pequeños necesarios para procesar documentos que de otro modo no cabrían en la memoria.
langchain.schema.Document representa una unidad arbitraria de texto con metadatos asociados, lo que la convierte en un bloque de construcción en langchain.
requests se utiliza para realizar solicitudes HTTP externas a las API.
botocore.client.Config es una clase de configuración que se utiliza para definir los ajustes de configuración de un cliente de AWS/IBM® Cloud Object Storage.
ibm_boto3 es el SDK de IBM® Cloud Object Storage para Python que ayuda a interactuar con el almacenamiento de objetos en la nube.
langchain.prompts.PromptTemplate ofrece una forma de crear instrucciones estructuradas y reutilizables para modelos de lenguaje.
langchain.tools.BaseTool es la clase base a partir de la cual se crean herramientas personalizadas que se pueden dar a los agentes de LangChain para su uso.
Este paso configura todas las herramientas y módulos que necesitamos para procesar texto, crear embeddings, almacenarlos en una base de datos vectorial e interactuar con el LLM de IBM® watsonx. Establece todas las partes necesarias para crear un sistema de RAG del mundo real, capaz de obtener, consultar y buscar una variedad de tipos de datos.
En este paso, cargaremos el PDF de la póliza de seguro desde IBM® Cloud Object Storage. El código lee el PDF, lee el contenido del texto y divide el texto en fragmentos más pequeños y manejables. Estos fragmentos se convierten en embeddings numéricos y se almacenan en un almacén de vectores FAISS que nos prepara para la búsqueda de similitud semántica posterior en el contexto local para optimizar los resultados de recuperación.
ibm_boto3.client permite al cliente interactuar con IBM® Cloud Object Storage.
Bucket es el nombre del bucket de almacenamiento de objetos en la nube que contiene el PDF.
object_key es el nombre del PDF en el bucket de almacenamiento de objetos en la nube.
cos_client.get_object(...).read() recupera el contenido del archivo PDF en el almacenamiento de objetos en la nube como bytes.
io.BytesIO convierte los bytes sin procesar del PDF en un flujo binario en memoria en un formato que puede utilizar PdfReader.
PdfReader crea un objeto que puede analizar y extraer texto del PDF.
page.extract_text() extrae el texto de una sola página en el PDF.
RecursiveCharacterTextSplitter está configurado para dividir el texto extraído en fragmentos de 500 caracteres con una superposición de 50 caracteres, manteniendo así todo en contexto.
splitter.split_text(text) ejecuta la división de todas las páginas del texto PDF en fragmentos más pequeños.
HuggingFaceEmbeddings carga un modelo de transformador de frases que ha sido previamente entrenado para convertir los fragmentos de texto en representaciones vectoriales densas.
FAISS.from_texts(chunks, embeddings) crea un índice FAISS en memoria que permite buscar fragmentos de texto por sus similitudes semánticas.
Este paso gestiona la ingesta completa de un documento PDF desde la nube hasta texto listo para LLM y una cómoda indexación para su recuperación en tiempo real.
En este paso, configurará el LLM de IBM® Granite para impulsar el razonamiento de su agente e integrarlo con la función de búsqueda web de Tavily. Los parámetros del LLM están configurados para respuestas objetivas y estables.
WatsonxLLM instancia el envoltorio LLM para IBM® watsonx, lo que permite la interacción con los modelos Granite.
model_id="ibm/granite-3-2b-instruct" es el modelo IBM® Granite (un modelo de instrucción de 2700 millones de parámetros) diseñado para tareas de IA generativa basadas en instrucciones.
class TavilySearch(BaseTool) define una herramienta LangChain personalizada para realizar búsquedas web mediante la API de Tavily.
tavily_tool = TavilySearch() crea una instancia ejecutable de la herramienta de búsqueda Tavily personalizada.
Cuando inicializamos watsonxLLM, los valores url, apikey y project_id de nuestras credenciales configuradas previamente se pasan para autenticar y conectarse al servicio. Sus parámetros, como "max_new_tokens": 300, limitan la longitud de la respuesta y "temperature": 0.2 controla la creatividad del resultado, favoreciendo que este sea más determinista.
La definición de la clase TavilySearch incluye una descripción de su función. Su lógica está contenida en el método def _run(self, query: str). En este método, realizamos una solicitud HTTP POST al endpoint de la API de Tavily, que incluye la TAVILY_API_KEY y la consulta de búsqueda en la carga útil JSON. A continuación, verificamos si hay algún error HTTP con response.raise_for_status() y analizamos la respuesta JSON para acceder al fragmento de contenido del primer resultado de la búsqueda.
Este paso configura el modelo de lenguaje para la generación de texto e incluye una herramienta de búsqueda web externa como una forma de aumentar el conocimiento del modelo de lenguaje.
Este paso define las diversas plantillas de instrucciones que guían el comportamiento del LLM en las diferentes etapas del proceso de RAG. Este enfoque incluye instrucciones para puntuar la relevancia de los fragmentos de documentos internos, reescribir las consultas de los usuarios para mejorar la búsqueda en la web y una nueva instrucción crítica para verificar la fuente de los resultados de la búsqueda web. También se definen funciones auxiliares para puntuar fragmentos y recuperarlos del almacén de vectores.
Este paso define las diversas plantillas de instrucciones que guían el comportamiento del LLM en las diferentes etapas del proceso de RAG. Instrucciones para puntuar la relevancia de los fragmentos de documentos internos, reescribir las consultas de los usuarios para mejorar la búsqueda en la web y una instrucción crítica para verificar que se incluyen la fuente de los resultados de la búsqueda web. También se definen funciones auxiliares para puntuar fragmentos y recuperarlos del almacén de vectores.
PromptTemplate.from_template es un servicio de LangChain para crear una plantilla reutilizable para crear instrucciones.
scoring_prompt_template define una instrucción que indica al LLM que actúe como evaluador y asigne una puntuación de relevancia (0-5) a un fragmento de contexto específico basado en una pregunta.
rewrite_prompt_template define una instrucción que guía al LLM para mejorar o aclarar la pregunta original de un usuario para la búsqueda.
CONTEXT_SOURCE_VERIFICATION_PROMPT define una instrucción que instruye al LLM a verificar si un fragmento de texto (por ejemplo, de una búsqueda web) procede de un contexto de política privado o de una fuente general o pública.
def score_chunks(chunks, query) define una función que toma una lista de trozos de texto y una consulta y luego utiliza el LLM para puntuar la relevancia de cada trozo.
def retrieve_from_vectorstore(query) define una función para recuperar los documentos más similares del almacén de vectores del FAISS.
Dentro de la función score_chunks, se inicializa una lista vacía de puntuaciones. Para cada fragmento, el scoring_prompt_template se formatea con la consulta y el trozo específicos. Esta instrucción formateada se envía al LLM y se elimina la respuesta. La función intenta extraer la puntuación entera (una puntuación binaria si se simplifica a relevante o no relevante) identificando la línea "Score:" en la respuesta del modelo. A continuación, el fragmento junto con su puntuación analizada o predeterminada se añade a la lista puntuada. Esta parte del sistema actúa como evaluador o calificador de recuperación.
La función retrieve_from_vectorstore implementa un vectorstore.similarity_search para encontrar los 8 fragmentos de documentos más relevantes basados en la consulta y recupera el page_content de estos objetos LangChain Document recuperados.
Este paso construye el andamiaje conceptual para el sistema de RAG correctiva para que tanto el LLM evalúe el contexto como la forma de recuperar el conocimiento de fuentes de conocimiento internas y externas.
La recuperación inicial es la función que escanea el almacén de vectores del PDF.
La puntuación de contexto lleva los fragmentos de PDF que se han recuperado a la puntuación de contexto según su relevancia.
Se recurre a tavily si no hay suficiente contexto relevante en el PDF (búsqueda web).
La verificación de la fuente es un paso impulsado por LLM que comprueba si los resultados de Tavily son relevantes para una política privada antes de usarlos. Esta función evita respuestas engañosas de los programas de salud pública.
Reescritura de consultas y segunda búsqueda en Tavily si todavía no hay un buen contexto, reescribe la consulta e intenta de nuevo la búsqueda en Tavily.
Decisión final cuando hay algún contexto relevante, se envía al LLM con una instrucción (estricta) para crear la respuesta. Si no hay un contexto relevante después de todos los intentos viables, envía una negativa cortés.
La primera pasada del parámetro policy_context_keywords le permite añadir términos específicos de su póliza (por ejemplo, su nombre, aseguradora) para ayudar a acotar las búsquedas de Tavily.
MIN_CONTEXT_LENGTH define la longitud mínima aceptable del contexto recuperado.
SIMILARITY_THRESHOLD define la puntuación mínima de relevancia que debe tener un fragmento para ser considerado "bueno".
def corrective_rag(...) define la función principal que orquesta todo el flujo de trabajo de RAG correctiva.
La función corrective_rag comienza creando retrieved_context_pieces para recopilar el contexto relevante. Primero obtiene y puntúa chunks_from_vectorstore del almacén de vectores de PDF en función de la consulta y, a continuación, score_chunks_vector evalúa su relevancia utilizando el modelo de lenguaje. Solo se conservan good_chunks_vector que cumplen el SIMILARITY_THRESHOLD. A continuación, se compila el current_context a partir de estas piezas.
Si el current_context es inferior a MIN_CONTEXT_LENGTH, el sistema intenta realizar una búsqueda web. Construye tavily_search_query, incorporando potencialmente policy_context_keywords. Se realiza una búsqueda directa (tavily_context_direct). Fundamentalmente, se crea un verification_prompt y se envía al LLM para determinar si el resultado de la búsqueda web (is_relevant_source) proviene de una política privada en lugar de un programa público. Si es SÍ, se añade el contexto.
Si el contexto sigue siendo insuficiente, el sistema se prepara para reescribir la consulta. Utiliza rewrite_prompt para obtener una improved_query del LLM y, a continuación, realiza una segunda búsqueda web (tavily_context_rewrite). Este nuevo contexto también se somete a la misma verificación de origen.
Por último, if len(current_context.strip()) == 0 es una verificación final. Si no se encuentra ningún contexto relevante después de todos los intentos, se devuelve un mensaje de rechazo predefinido. De lo contrario, se crea un final_prompt con todo el contexto verificado y se envía al modelo de lenguaje para generar su respuesta final.
Toda la función corrective_rag gestiona en detalle las funciones de recuperación, puntuación y verificación por etapas del RAG correctivo. Permite la actualización constante de la base de conocimientos y del flujo de conocimientos, y aporta el beneficio de ofrecer respuestas sólidas y contextualizadas.
Por último, ejecute la función corrective_rag con una consulta de ejemplo. Es crucial proporcionar policy_context_keywords que sean específicas de su documento PDF. Estas palabras clave ayudarán a que la búsqueda web de Tavily sea más relevante para su política real, evitando que la información general o sobre programas de salud pública contamine su contexto.
Observe las sentencias de impresión para conocer la longitud del contexto y los resultados de la verificación para comprender el flujo de información.
policy_specific_keywords = ["Super Star Health", "Care Health Insurance"] define una lista de palabras clave que son relevantes para la póliza de seguro cargada, lo que ayuda a reducir los resultados de búsqueda web.
query = "..." define la pregunta particular que un usuario podría hacer.
result = corrective_rag(query, policy_context_keywords=policy_specific_keywords) llama a la función principal corrective_rag y pasa la consulta del usuario y las palabras clave específicas de la política para comenzar todo el proceso de RAG.
print("\n FINAL ANSWER (...)") muestra un encabezado claro antes de imprimir la respuesta generada.
print(result) genera el resultado final devuelto por el sistema corrective_rag.
Este paso muestra cómo invocar el sistema de RAG correctiva completo con una consulta de muestra y palabras clave, demostrando su funcionalidad de principio a fin en un escenario del mundo real.
La RAG correctiva implementada coordinó plenamente una base de conocimientos PDF interna con un servicio externo (Tavily) para recuperar información exhaustiva para solicitudes complejas.
Evaluó y filtró con precisión el contexto recuperado mediante la puntuación basada en LLM y la verificación de fuentes críticas para garantizar que se utiliza información válida y fiable.
El sistema demostró la capacidad de mejorar la búsqueda externa reescribiendo de forma inteligente las consultas de los usuarios para solicitar información más específica y de mayor calidad.
Al utilizar la generación restringida, se generaba comúnmente una respuesta fiable y contextualmente precisa y el sistema se negaba cortésmente a responder si no había suficiente información verificada conocida.
Este ejemplo demostró cómo se pueden utilizar LangChain y los LLM de IBM® Granite en watsonx para desarrollar aplicaciones potentes y fiables basadas en IA en dominios sensibles, como hacer preguntas sobre pólizas de seguros.
Cree, implemente y gestione potentes asistentes y agentes de IA que automaticen flujos de trabajo y procesos con IA generativa.
Construya el futuro de su empresa con soluciones de IA en las que puede confiar.
Los servicios de IA de IBM Consulting ayudan a reinventar la forma de trabajar de las empresas usando IA para la transformación.