Protección de la información sensible y de la PII en RAG con Elasticsearch y LlamaIndex

Cómo proteger datos sensibles y de PII en una aplicación RAG con Elasticsearch y LlamaIndex.

Elasticsearch tiene integraciones nativas con las herramientas y proveedores líderes en la industria de IA generativa. Echa un vistazo a nuestros webinars sobre cómo ir más allá de los conceptos básicos de RAG o crear apps listas para la producción con la base de datos vectorial de Elastic.

Para crear las mejores soluciones de búsqueda para tu caso de uso, inicia una prueba gratuita en el cloud o prueba Elastic en tu máquina local ahora mismo.

En esta publicación analizaremos formas de proteger la Información Personal Identificable (PII) y los datos sensibles al emplear LLMs públicos en un flujo RAG (Generación Aumentada por Recuperación). Exploraremos el enmascaramiento de la PII y datos sensibles empleando librerías de código abierto y expresiones regulares, así como el uso de LLMs locales para enmascarar los datos antes de invocar un LLM público.

Antes de empezar, repasemos algunos términos que usamos en esta publicación.

Terminología

LlamaIndex es un marco de datos líder para construir aplicaciones LLM (Grandes Modelos de Lenguaje). LlamaIndex proporciona abstracciones para las distintas etapas de la construcción de una aplicación RAG (Generación Aumentada por Recuperación). Frameworks como LlamaIndex y LangChain proporcionan abstracciones para que las aplicaciones no se acoplen estrechamente a las APIs de ningún LLM específico.

Elasticsearch es ofrecido por Elastic. Elastic es líder en el sector detrás de Elasticsearch, un almacén de datos escalable y base de datos vectoriales que soporta búsqueda de texto completo para mayor precisión, búsqueda vectorial para comprensión semántica y búsqueda híbrida para lo mejor de ambos mundos. Elasticsearch es un motor de búsqueda y análisis distribuido y RESTful, almacén de datos escalable y base de datos vectorial. Las capacidades de Elasticsearch que empleamos en este blog están disponibles en la versión Gratis y Abierta de Elasticsearch.

La Generación Aumentada por Recuperación (RAG) es una técnica/patrón de IA en la que los LLMs reciben conocimientos externos para generar respuestas a las consultas de los usuarios. Esto permite adaptar las respuestas de los LLM a un contexto específico y ser menos genéricas.

Las incrustaciones son representaciones numéricas del significado de texto/medios. Son representaciones de información de alta dimensión en dimensiones inferiores.

RAG y Protección de Datos

Generalmente, los Grandes Modelos de Lenguaje (LLMs) son buenos generando respuestas basadas en la información disponible en el modelo que puede capacitar con datos de Internet. Sin embargo, para aquellas consultas donde la información no está disponible en el modelo, los LLMs deben proporcionar con conocimientos externos o detalles específicos que no estén contenidos en el modelo. Dicha información puede estar en tu base de datos o en tu sistema de conocimiento interno. La Generación Aumentada por Recuperación (RAG) es una técnica en la que, para una consulta de usuario dada, primero recuperas el contexto/información relevante de sistemas externos (a los LLMs) (por ejemplo, tu base de datos) y envías ese contexto junto con la consulta de usuario a un LLM para generar una respuesta más específica y relevante.

Esto hace que la técnica RAG sea muy eficaz para aplicaciones en respuesta a preguntas, creación de contenido y en cualquier lugar, un conocimiento profundo del contexto y el detalle es beneficioso.

Como resultado, en una cadena RAG corres el riesgo de exponer información interna como PII (Información Personal Identificable) e información sensible (por ejemplo, nombres, fechas de nacimiento, números de cuenta, etc.) a los LLMs públicos.

Aunque tus datos son seguros cuando usas una base de datos vectorial como Elasticsearch (a través de varias palancas como Control de Acceso basado en Roles, Seguridad a Nivel de Documentos , etc.), hay que tener cuidado al enviar datos fuera a un LLM público.

Proteger la Información Personalmente Identificable (PII) y los datos sensibles es crucial al emplear grandes modelos de lenguaje (LLMs) por varias razones:

  • Cumplimiento de la privacidad: Muchas regiones tienen regulaciones estrictas, como el Reglamento General de Protección de Datos (RGPD) en Europa o la Ley de Privacidad del Consumidor de California (CCPA) en Estados Unidos, que exigen la protección de los datos personales. El cumplimiento de estas leyes es necesario para evitar consecuencias legales y multas.
  • Confianza del usuario: Garantizar la confidencialidad e integridad de la información sensible genera confianza en los usuarios. Los usuarios tienen más probabilidades de emplear e interactuar con sistemas que creen que protegerán su privacidad.
  • Seguridad de los datos: La protección frente a brechas de datos es esencial. Los datos sensibles expuestos a los LLMs sin las salvaguardas adecuadas pueden ser susceptibles a robo o mal uso, lo que puede provocar daños como el robo de identidad o el fraude financiero.
  • Consideraciones éticas: Éticamente, es importante respetar la privacidad de los usuarios y manejar sus datos de forma responsable. Un mal manejo de la PII puede provocar discriminación, estigmatización u otros impactos sociales negativos.
  • Reputación empresarial: Las compañías que no protegen datos sensibles pueden sufrir daños en su reputación, lo que puede tener efectos negativos a largo plazo en su negocio, incluyendo la pérdida de clientes e ingresos.
  • Reducción de los riesgos de abuso: El manejo seguro de datos sensibles ayuda a prevenir el uso malicioso de los datos o del modelo, como capacitar los modelos con datos sesgados o usar los datos para manipular o dañar a individuos.

En general, es necesaria una protección robusta de las PII y datos sensibles para garantizar el cumplimiento legal, mantener la confianza de los usuarios, garantizar la seguridad de los datos, mantener estándares éticos, proteger la reputación empresarial y reducir el riesgo de abuso.

Resumen rápido

En la publicación anterior hablamos de cómo implementar la experiencia de preguntas frecuentes empleando una técnica RAG con Elasticsearch como base de datos vectorial, empleando LlamaIndex y un LLM Mistral que se ejecuta localmente. Aquí vamos a construir sobre eso.

Leer la publicación anterior es opcional, ya que ahora vamos a hablar o resumir rápidamente lo que hicimos en la publicación anterior.

Teníamos un conjunto de datos de ejemplo de conversaciones en centros de llamadas entre agentes y clientes de una compañía de seguros de hogar ficticia. Construimos una aplicación RAG sencilla que respondía a preguntas como "¿Por qué tipo de problemas relacionados con el agua presentan reclamaciones los clientes?".

A grandes rasgos, así es como se veía el flujo.

Durante la fase de Indexación, cargamos e indexamos documentos usando la canalización LlamaIndex. Los documentos se agrupaban en fragmentos y se almacenaban en la base de datos vectorial Elasticsearch junto con sus incrustaciones.

Durante la fase de consulta, cuando el usuario hacía una pregunta, LlamaIndex recuperaba documentos similares en top-K que eran relevantes para la consulta. Estos documentos relevantes para el top-K junto con la consulta se enviaban al LLM Mistral que se ejecutaba localmente, que luego generaba la respuesta para ser enviada de vuelta al usuario. No dudes en leer la publicación anterior o explorar el código.

En la publicación anterior teníamos el LLM funcionando localmente. Sin embargo, en producción puede que quieras usar un LLM externo proporcionado por varias compañías como OpenAI, Mistral, Anthropic , etc. Puede ser porque tu caso de uso necesita un modelo fundamental más amplio o porque ejecutar localmente no es una opción debido a necesidades de producción empresarial como escalabilidad, disponibilidad, rendimiento, etc.

Introducir un LLM externo en tu pipeline RAG te expone al riesgo de filtrar inadvertidamente información sensible y PII a los LLMs. En esta publicación exploraremos opciones sobre cómo enmascarar la información de PII como parte de tu pipeline RAG antes de enviar documentos a un LLM externo.

RAG con un LLM público

Antes de hablar sobre cómo proteger tu PII e información sensible en una cadena RAG, primero construiremos una aplicación RAG sencilla empleando LlamaIndex, la base de datos Elasticsearch Vector y OpenAI LLM.

Prerrequisitos

Necesitaremos lo siguiente.

  • Elasticsearch está en funcionamiento como base de datos vectorial para almacenar los embeddings. Sigue las instrucciones de la publicación anterior sobre cómo instalar Elasticsearch.
  • Abre las claves API de IA.

Aplicación sencilla de RAG

Para referencia, el código completo se puede encontrar en este Repositorio de Github(branch:protecting-pii). Clonar el repositorio es opcional, ya que repasaremos el código a continuación.

En tu IDE favorito, crea una nueva aplicación en Python con los siguientes 3 archivos.

  • index.py donde va el código relacionado con la indexación de datos.
  • query.py donde va el código relacionado con la consulta y la interacción con LLM.
  • .env donde van propiedades de configuración como las claves de API.

Necesitamos instalar algunos paquetes. Comenzamos creando un nuevo entorno virtual de Python en la carpeta raíz de tu aplicación.

Activa el entorno virtual e instala los paquetes requeridos a continuación.

Configura las propiedades de conexión de OpenAI y Elasticsearch en el archivo .env archivo.

Datos de indexación

Descarga el archivo conversations.json que contiene conversaciones entre clientes y agentes del centro de llamadas de nuestra ficticia compañía de seguros de hogar. Coloca el archivo en el directorio raíz de la aplicación junto a los 2 archivos python y el archivo .env Archivo que creaste antes. A continuación se muestra un ejemplo del contenido del archivo.

Más allá del código de abajo en index.py que se encarga de indexar los datos.

Ejecutar el código anterior para ver crea un índice en Elasticsearch, almacena los embeddings en el índice de Elasticsearch llamado convo_index.

Si necesitas explicación sobre LlamaIndex IngestionPipeline, consulta la publicación anterior en la sección Crear Pipeline.

Consulta

En la publicación anterior usamos un LLM local para hacer consultas.

En esta publicación usamos un LLM público, OpenAI, como se muestra a continuación.

El código anterior muestra la respuesta de OpenAI como se indica a continuación.

Los clientes presentaron diversas reclamaciones relacionadas con el agua, incluyendo problemas como daños por agua en sótanos, tuberías rotas, daños por granizo en los tejados y denegación de reclamaciones por motivos como falta de notificación a tiempo, problemas de mantenimiento, desgaste gradual y daños preexistentes. En cada caso, los clientes expresaron frustración por las denegaciones de reclamaciones y buscaron evaluaciones y decisiones justas respecto a sus reclamaciones.

Ocultar la PII en RAG

Lo que cubrimos hasta ahora implica enviar documentos tal cual a OpenAI junto con la consulta del usuario.

En la tubería RAG, tras recuperar el contexto relevante de un almacén vectorial, tenemos la oportunidad de enmascarar la información personal personal y sensible antes de enviar la consulta y el contexto al LLM.

Hay varias formas de enmascarar la información de la PII antes de enviarla a un LLM externo, cada una con su propio mérito. A continuación analizamos algunas de las opciones

  1. Empleando bibliotecas de PLN como spacy.io o Presidio (biblioteca de código abierto mantenida por Microsoft).
  2. Uso de LlamaIndex desde el primer momento NERPIINodePostprocessor.
  3. Uso de LLMs locales mediante PIINodePostprocessor

Una vez que implementes la lógica de enmascaramiento usando cualquiera de las formas anteriores, podrías configurar el LlamaIndex IngestionPipeline con un PostProcesador (tu propio personalizado o cualquiera de los PostProcessors listos para usar de LlamaIndex).

Uso de bibliotecas de PLN

Como parte de la cadena RAG podríamos enmascarar datos sensibles usando bibliotecas de PLN. Usaremos el paquete spacy.io en esta demo.

Crea un nuevo query_masking_nlp.py de archivo y agrega el código que aparece a continuación.

La respuesta del LLM se muestra a continuación.

Los clientes presentaron diversas reclamaciones relacionadas con el agua, incluyendo problemas como daños por agua en sótanos, tuberías rotas, daños por granizo en los tejados e inundaciones durante lluvias intensas. Estas reclamaciones provocaron frustraciones debido a denegaciones basadas en motivos como la falta de notificación oportuna, problemas de mantenimiento, desgaste gradual y daños preexistentes. Los clientes expresaron decepción, estrés y carga financiera como resultado de estas denegaciones de reclamaciones, buscando evaluaciones justas y revisiones exhaustivas de sus reclamaciones. Algunos clientes también sufrieron retrasos en la tramitación de las reclamaciones, lo que provocó una mayor insatisfacción con el servicio prestado por la compañía de seguros.

En el código anterior, al crear el Llama Index QueryEngine, suministramos un CustomPostProcessor.

La lógica que invoca el QueryEngine en está definida en el método _postprocess_nodes de CustomPostProcessor. Estamos usando la biblioteca SpaCy.io para detectar Entidades Nombradas en nuestro y luego usamos algunas expresiones regulares para reemplazar esos nombres, así como información sensible, antes de enviar los documentos al LLM.

Como ejemplo a continuación, se presentan partes de conversaciones originales y la conversación enmascarada creada por el CustomPostProcessor.

Texto original:

Cliente: Hola, soy Matthew Lopez, la fecha de nacimiento es el 12 de octubre de 1984 y vivo en 456 Cedar St, Smalltown, NY 34567. Mi número de póliza es TUV8901. Agente: Buenas tardes, Matthew. ¿En qué puedo ayudarlo hoy? Cliente: Hola, estoy extremadamente decepcionado con la decisión de su compañía de denegar mi reclamación.

Texto enmascarado por el CustomPostProcessor.

Cliente: Hola, soy [ENMASCARADO], [ENMASCARADO] es [ENMASCARADO NACIMIENTO], y vivo en 456 Cedar St, [ENMASCARADO], [ENMASCARADO] 34567. Mi número de póliza es [MASKED]. Agente: Buenas tardes, [ENMASCARADO]. ¿En qué puedo ayudarlo hoy? Cliente: Hola, estoy extremadamente decepcionado con la decisión de su compañía de denegar mi reclamación.

Nota:

Identificar y enmascarar la información personal personal y la información sensible no es una tarea sencilla. Cubrir diversos formatos y semánticas de información sensible requiere un buen conocimiento de tu dominio y datos. Aunque el código presentado arriba puede funcionar para algunos casos de uso, puede que tengas que modificar según tus necesidades y pruebas.

Usando el LlamaIndex de fábrica

LlamaIndex facilitó la protección de la información de PII en una cadena RAG al introducir NERPIINodePostprocessor.

La respuesta es la siguiente que se muestra

Los clientes presentaron reclamaciones relacionadas con incendios respecto a daños en sus propiedades. En un caso, se denegó una reclamación por daños por incendio en un garaje debido a que el incendio provocado quedó excluido de la cobertura. Otro cliente presentó una reclamación por daños de incendio en su casa, que estaba cubierta por su póliza. Además, un cliente informó de un incendio en la cocina y le cercioraron que los daños por incendio estaban cubiertos.

Uso de LLMs locales mediante

También podríamos aprovechar un LLM que funcione localmente o en tu red privada para hacer el trabajo de enmascaramiento antes de enviar los datos a un LLM público.

Usaremos Mistral funcionando en Ollama en tu máquina local para hacer el enmascaramiento.

Ejecutar Mistral localmente

Descarga e instala Ollama. Luego de instalar Ollama, ejecuta este comando para descargar y ejecutar mistral

Puede que tardes unos minutos en descargar y ejecutar el modelo localmente por primera vez. Verifica si el mistral está funcionando haciendo una pregunta como la siguiente: "Escribe un poema sobre nubes" y verifica si el poema te gusta. Mantén a Ollama funcionando, ya que tendremos que interactuar con el modelo mistral más adelante mediante código.

Crea un archivo nuevo llamado query_masking_local_LLM.py y agrega el código de abajo.

La respuesta es algo parecido a la que se muestra a continuación

Los clientes presentaron reclamaciones relacionadas con incendios respecto a daños en sus propiedades. En un caso, se denegó una reclamación por daños por incendio en un garaje debido a que el incendio provocado quedó excluido de la cobertura. Otro cliente presentó una reclamación por daños de incendio en su casa, que estaba cubierta por su póliza. Además, un cliente informó de un incendio en la cocina y le cercioraron que los daños por incendio estaban cubiertos.

Conclusión

En esta publicación mostramos cómo se puede proteger la PII y los datos sensibles al usar LLMs públicos en un flujo RAG. Demostramos múltiples formas de lograrlo. Se recomienda encarecidamente probar estos enfoques según tu caso de uso y necesidades antes de adoptarlos.

Contenido relacionado

¿Estás listo para crear experiencias de búsqueda de última generación?

No se logra una búsqueda suficientemente avanzada con los esfuerzos de uno. Elasticsearch está impulsado por científicos de datos, operaciones de ML, ingenieros y muchos más que son tan apasionados por la búsqueda como tú. Conectemos y trabajemos juntos para crear la experiencia mágica de búsqueda que te dará los resultados que deseas.

Pruébalo tú mismo