Garantir des déploiements RAG sécurisés et respectueux des autorisations
Dans le domaine en évolution rapide de l’intelligence artificielle, la génération augmentée par récupération (RAG) s’est imposée comme une approche puissante pour améliorer les capacités des modèles génératifs tels que la série GPT d’OpenAI et Gemini de Google. Cependant, un grand potentiel implique une responsabilité importante, notamment lorsqu’il s’agit de protéger les données sensibles et de garantir la conformité aux réglementations en matière de confidentialité.
Alors que les organisations s’appuient de plus en plus sur des solutions pilotées par l’IA, il est crucial de comprendre les implications de ces technologies en matière de sécurité. La mise en œuvre de mesures de sécurité solides qui protègent non seulement les données, mais renforcent également la confiance des utilisateurs, est essentielle pour des applications RAG prêtes pour la production.
Lors d’un récent Unstructured Data Meetup organisé par Zilliz, Oz Wasserman, cofondateur de Opsin, a mis en évidence les principales considérations de sécurité pour les déploiements RAG, en soulignant l’importance de l’anonymisation des données, du chiffrement fort, de la validation des entrées/sorties et de contrôles d’accès robustes, entre autres mesures de sécurité essentielles.
Dans ce blog, nous aborderons les aspects clés des déploiements RAG sécurisés et sensibles aux autorisations. Nous parcourrons également un exemple de notebook d’un pipeline RAG utilisant la base de données vectorielle Milvus et des postprocesseurs LlamaIndex conçus pour supprimer les informations sensibles, garantissant ainsi la confidentialité des données et la conformité.
Diagramme d’architecture RAG
Dans sa présentation, Oz a commencé par expliquer une architecture RAG fondamentale similaire à celle illustrée dans la Figure 1. Essentiellement, un système RAG améliore un grand modèle de langage (LLM) en intégrant une base de connaissances alimentée par une base de données vectorielle, qui stocke des documents afin de récupérer du contenu pertinent en réponse à la requête d’un utilisateur. Cette approche améliore la précision, garantit une plus grande pertinence contextuelle et minimise les hallucinations souvent observées dans les sorties de LLM autonomes.
Cependant, ce pipeline de base ne comporte pas de mesures de sécurité spécifiques, sauf si elles sont intégrées aux différentes étapes. Oz a mis en avant un schéma de flux de travail RAG (voir Figure 2) de Ken Huang de DistributedApps.ai, dans lequel des contrôles de sécurité peuvent être mis en œuvre tout au long du pipeline RAG :
Étape Source de données/VectorDB
Étape de récupération
Étape de génération
Figure- Vector database facilitating RAG chatbot.png
Figure 1 : Architecture RAG de base
Figure 2- Detailed RAG Architecture (Author- Ken Huang)
Figure 2 : Architecture RAG détaillée (Auteur : Ken Huang)
Étape Source de données/VectorDB
Les bases de données vectorielles telles que Milvus et Zilliz Cloud (le Milvus géré) stockent, indexent et récupèrent des embeddings vectoriels convertis à partir de données non structurées. Elles constituent des référentiels critiques d’informations précieuses. Cependant, elles peuvent également devenir des cibles de violations de données ou d’accès non autorisés, ce qui rend nécessaire la mise en œuvre de stratégies de protection robustes telles que le chiffrement, le contrôle d’accès ou l’anonymisation des données.
Figure 3- Source de données : contrôles de sécurité VectorDB.png
Figure 3 : Contrôles de sécurité de la source de données/VectorDB
Le premier volet de sécurité se trouve dans l’anonymisation des données. Les données contiennent des informations personnelles sensibles, communément appelées informations d’identification personnelle (PII). Ces données doivent être anonymisées afin de protéger la vie privée des individus. Cette étape est obligatoire avant tout traitement des données afin de garantir que ces informations ne puissent pas être retracées jusqu’à des personnes spécifiques.
Une fois les données anonymisées, elles peuvent être indexées et des embeddings peuvent être générés pour permettre la recherche sémantique afin de récupérer du contenu pertinent. À ce stade, il est important de définir qui peut stocker et récupérer les données dans et depuis la base de données vectorielle, autrement dit, qui y a accès. La mise en œuvre de contrôles d’accès stricts est essentielle pour empêcher tout accès non autorisé, qui pourrait entraîner une manipulation ou une fuite des données.
Le contrôle d’accès peut être décomposé en plusieurs étapes :
Authentification : S’assurer que l’utilisateur vérifie son identité, généralement à l’aide de méthodes comme OAuth 2.0.
Autorisation : En fonction de l’identité vérifiée, des permissions et des droits d’accès spécifiques sont accordés à l’utilisateur.
Traçabilité : Surveiller l’accès pour garantir que toute tentative d’accès aux données est consignée et peut être suivie, fournissant ainsi une piste d’audit pour la conformité en matière de sécurité.
Ces mesures contribuent à protéger la base de données vectorielle et garantissent que seuls les utilisateurs autorisés peuvent interagir avec des données sensibles.
Une autre couche de sécurité peut être ajoutée avec le chiffrement afin de rendre les données inintelligibles au repos (lorsqu’elles sont stockées) ou en transit (lorsqu’elles sont transmises). Le chiffrement traditionnel utilise des clés de chiffrement, mais des techniques plus avancées telles que la confidentialité différentielle ou la décentralisation et le sharding sont également de plus en plus adoptées pour renforcer la sécurité des données.
Zilliz Cloud est un service de base de données vectorielle entièrement géré, propulsé par Milvus. Il offre toutes ces mesures essentielles de sécurité des données. Il peut fournir d’autres solutions, comme Private Link, pour éviter l’accès à l’internet public, la sauvegarde et la restauration afin de garantir des sauvegardes régulières et sécurisées des données, ainsi que la récupération de la base de connaissances en cas de perte de données.
Figure 6- Sécurité d’entreprise multicouche de Zilliz
Figure 6 : Sécurité d’entreprise multicouche de Zilliz (Source)
Étape de récupération
L’étape de récupération est une autre étape critique où les préoccupations de sécurité doivent être prises en compte. Comme à l’étape précédente, contrôler l’accès à la base de connaissances au moyen de requêtes est essentiel. De plus, au cours de cette étape, plusieurs risques de sécurité doivent également être atténués :
Validation des requêtes : La validation des requêtes est cruciale pour prévenir les attaques par injection de prompt. Cette approche garantit que les entrées utilisateur n’exploitent pas les vulnérabilités du système, ce qui pourrait potentiellement entraîner un accès non autorisé ou une manipulation des données.
Risques liés à la recherche de similarité : Il est également important de gérer les risques associés aux recherches de similarité. Des mesures appropriées doivent être mises en place pour garantir que la recherche de similarité n’expose pas par inadvertance des informations sensibles ni ne fournisse un accès non autorisé à des données restreintes.
Figure 7- Étape de validation des requêtes
Figure 7 : Étape de validation des requêtes
Oz a partagé un exemple (voir Figure 8) d’injection de prompt lors de la présentation d’un modèle interne. C’est un bon exemple de manipulation de prompt, où le prompt est modifié pour récupérer des données.
Figure 8- Exemple d’injection de prompt
Figure 8 : Exemple d’injection de prompt
De plus, Oz a discuté de plusieurs risques associés à la recherche de similarité, notamment :
Fuite de données : En manipulant les requêtes de similarité, les attaquants peuvent influencer le mécanisme de recherche afin de récupérer indirectement des données sensibles.
Manipulation des résultats de recherche : Les attaquants pourraient modifier le processus de recherche afin d’influencer les résultats récupérés, entraînant une exposition potentielle d’informations restreintes.
Reconnaissance et analyse des schémas : Les attaquants peuvent analyser les schémas dans les requêtes et réponses de recherche afin de cartographier la structure de la base de données et d’obtenir des informations sur les données stockées.
Épuisement des ressources : Des requêtes continues ou excessives pourraient entraîner des conditions de déni de service, épuisant les ressources système et réduisant la disponibilité pour les autres utilisateurs.
Nous constatons que des techniques de sécurité similaires doivent être mises en œuvre pour l’étape de récupération, comme le contrôle d’accès ou la validation des données. De plus, le chiffrement (en transit) doit être pris en compte, car les données sont transmises entre les composants.
Étape de génération
La dernière étape du pipeline RAG est l’étape de génération, où le Large Language Model (LLM) génère des réponses à partir du contenu récupéré dans la base de données vectorielle. Bien que le LLM soit l’acteur central à cette étape, des problèmes de sécurité et de conformité peuvent survenir selon la nature des données utilisées pour entraîner le modèle. Certains risques clés incluent :
Violations de la confidentialité des données : Le LLM peut révéler par inadvertance des informations sensibles ou privées s’il a été entraîné sur des données comprenant des informations personnellement identifiables (PII) ou d’autres contenus confidentiels. Cela pourrait entraîner des violations de réglementations sur la confidentialité telles que le RGPD ou HIPAA.
Manipulation des sorties : Les attaquants pourraient manipuler la sortie du LLM en influençant les requêtes d’entrée, entraînant la génération de contenu malveillant ou trompeur. Cela est particulièrement préoccupant dans les environnements où les sorties sont considérées comme fiables sans vérification.
Biais et contenu offensant : Si les données d’entraînement contiennent des éléments biaisés ou offensants, le LLM pourrait produire des réponses biaisées ou offensantes, ce qui pourrait entraîner des responsabilités juridiques, en particulier dans les environnements de production.
La prise en compte de ces risques nécessite un post-traitement soigneux du contenu généré, notamment des techniques telles que :
Filtrage du contenu : Filtrer automatiquement les sorties afin de détecter et bloquer le contenu sensible, biaisé ou offensant.
Validation des sorties : Valider la réponse du modèle afin de s’assurer qu’elle respecte les politiques de sécurité et les normes réglementaires avant de la fournir à l’utilisateur.
Affinage du modèle : S’assurer que le modèle est affiné avec des données conformes aux réglementations et appliquer des stratégies d’apprentissage par renforcement afin d’éviter les sorties nuisibles.
En intégrant ces stratégies, l’étape de génération peut être rendue plus sûre et plus fiable, et ajoute une couche de sécurité.
Examinons maintenant un exemple d’anonymisation des données, où différents postprocesseurs LlamaIndex seront comparés et un exemple de violations de la confidentialité des données sera présenté.
RAG sécurisé avec LlamaIndex et Milvus
Le notebook suivant est un exemple de pipeline RAG construit avec LlamaIndex comme framework LLM, Milvus comme base de données vectorielle, et trois modules différents spécialisés dans le masquage des PII : l’un utilisant un modèle NER de Hugging Face, un autre utilisant un LLM (OpenAI) et Presidio, une bibliothèque Microsoft.
Vous pouvez également consulter le code complet dans ce notebook colab.
Étape 1 : Configurer les variables d’environnement
Nous avons besoin d’une clé OpenAI pour tester le module en utilisant les modèles OpenAI.
from google.colab import userdata
import os
os.environ["OPENAI_API_KEY"] = userdata.get('OPENAI_API_KEY')
Étape 2 : Définir un texte avec des données privées
Tout d’abord, nous définissons un court texte qui contient des informations privées comme des numéros de carte de crédit, des noms ou des dates de naissance.
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.core.schema import TextNode, NodeWithScore
text = """
Hi, I'm Sarah Mitchell, and I just got a new credit card with the number 3714-496089-47322.
My personal email is sarah.mitchell@mailbox.com, and I'm currently based in Sydney.
By the way, I tried paying my utility bill with card number 6011-5832-9109-1726, but it didn't work.
For my bank transactions, I use this IBAN: NL91ABNA0417164300.
Also, can you help me with my Wi-Fi issues? I keep getting blocked by IP address 203.0.113.15.
I've shared a family photo on my personal blog at https://www.sarahs-lifediary.org/.
Oh, and my grandfather, George Stone, was born in 1921, while my grandmother, Emily Clarkson, was born in 1925.
Last question--what's the spending limit on my main card, the one ending in 8473?
"""
node = TextNode(text=text)
Étape 3 : Modèle NER pour le masquage des PII : NERPIINodePostprocessor
NERPIINodePostprocessor est un module de Llama Index qui masque ces informations à l’aide d’un modèle Hugging Face spécialisé dans la NER (reconnaissance d’entités nommées).
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.core.schema import TextNode, NodeWithScore
processor = NERPIINodePostprocessor()
new_nodes = processor.postprocess_nodes([NodeWithScore(node=node)])
print(new_nodes[0].node.get_text())
Nous voyons que ce modèle spécifique masque certaines informations, mais des données privées restent visibles. Utiliser cette approche représenterait donc une fuite de données. Par conséquent, un autre modèle ou une autre approche doit être utilisé.
"""
Output:
Hi, I'm [PER_9], and I just got a new credit card with the number 3714-496089-47322.
My personal email is sarah.mitchell@mailbox.com, and I'm currently based in [LOC_169].
By the way, I tried paying my utility bill with card number 6011-5832-9109-1726, but it didn't work.
For my bank transactions, I use this IBAN: NL91ABNA0417164300.
Also, can you help me with my Wi-[MISC_374] issues? I keep getting blocked by IP address 203.0.113.15.
I've shared a family photo on my personal blog at https://www.sarahs-lifediary.org/.
Oh, and my grandfather, [PER_545], was born in 1921, while my grandmother, [PER_599], was born in 1925.
Last question--what's the spending limit on my main card, the one ending in 8473?
"""
Étape 4 : LLM pour le masquage des PII : PIINodePostprocessor
PIINodePostprocessor est un module de Llama Index qui utilise un modèle LLM pour masquer les informations sensibles. Pour tester l’efficacité de cette approche, nous utiliserons le modèle OpenAI par défaut.
from llama_index.core.postprocessor import PIINodePostprocessor
from llama_index.core.schema import TextNode, NodeWithScore
from llama_index.llms.openai import OpenAI
processor = PIINodePostprocessor(llm=OpenAI())
new_nodes = processor.postprocess_nodes([NodeWithScore(node=node)])
print(new_nodes[0].node.get_text())
En suivant cette approche, le modèle peut reconnaître toutes les informations sensibles et les masquer en conséquence.
"""
Output:
Bonjour, je suis [NAME1] [NAME2], et je viens de recevoir une nouvelle carte de crédit avec le numéro [CREDIT_CARD_NUMBER1].
Mon adresse e-mail personnelle est [EMAIL], et je suis actuellement basé(e) à [CITY].
Au fait, j’ai essayé de payer ma facture de services publics avec le numéro de carte [CREDIT_CARD_NUMBER2], mais cela n’a pas fonctionné.
Pour mes transactions bancaires, j’utilise cet IBAN : [IBAN].
Aussi, pouvez-vous m’aider avec mes problèmes de Wi-Fi ? Je suis constamment bloqué(e) par l’adresse IP [IP_ADDRESS].
J’ai partagé une photo de famille sur mon blog personnel à [URL].
Oh, et mon grand-père, [NAME3] [NAME4], est né le [DATE1], tandis que ma grand-mère, [NAME5] [NAME6], est née le [DATE2].
Dernière question--quelle est la limite de dépenses de ma carte principale, celle qui se termine par [CREDIT_CARD_ENDING].
"""
Étape 5 : Presidio pour le masquage des PII
Enfin, nous testons Presidio, une bibliothèque Microsoft qui masque les informations sensibles à l’aide d’un modèle Spacy spécialisé dans la NER.
from llama_index.postprocessor.presidio import PresidioPIINodePostprocessor
from llama_index.core.schema import TextNode, NodeWithScore
from llama_index.llms.openai import OpenAI
processor = PresidioPIINodePostprocessor()
new_nodes = processor.postprocess_nodes([NodeWithScore(node=node)])
print(new_nodes[0].node.get_text())
Cette fois, nous voyons que le modèle peut masquer toutes les informations sauf le numéro de carte de crédit, car il le considère en partie comme un permis de conduire. Dans l’étape suivante, nous testerons plusieurs requêtes avec ce modèle et montrerons comment des violations de la confidentialité des données sont possibles parce qu’une partie du numéro de carte de crédit est disponible.
"""
Output:
Hi, I'm <PERSON_3>, and I just got a new credit card with the number 3714-<US_DRIVER_LICENSE_1>-47322.
My personal email is <EMAIL_ADDRESS_1>, and I'm currently based in <LOCATION_1>.
By the way, I tried paying my utility bill with card number <IN_PAN_1>9109-1726, but it didn't work.
For my bank transactions, I use this IBAN: <IBAN_CODE_1>.
Also, can you help me with my Wi-Fi issues? I keep getting blocked by IP address <IP_ADDRESS_1>.
I've shared a family photo on my personal blog at <URL_1>
Oh, and my grandfather, <PERSON_2>, was born in <DATE_TIME_2>, while my grandmother, <PERSON_1>, was born in <DATE_TIME_1>.
Last question--what's the spending limit on my main card, the one ending in 8473?
"""
Étape 6 : Récupération à l’aide de Milvus
Tout d’abord, créons une base de données vectorielle Milvus pour stocker notre texte.
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore
vector_store = MilvusVectorStore(
uri="./milvus_demo.db", dim=1536, overwrite=True
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex([n.node for n in new_nodes], storage_context=storage_context)
Ensuite, testons quelques requêtes.
Cette première requête fonctionne correctement. Elle nous fournit la bonne réponse et garde les informations masquées.
response = index.as_query_engine().query(
"What is the name of the person?"
)
print(str(response))
"""
Output:
The name of the person is <PERSON_3>.
"""
Maintenant, nous essayons d’obtenir le numéro de carte de crédit, et nous voyons que nous obtenons le numéro complet avec une partie masquée comme permis de conduire.
response = index.as_query_engine().query(
"What is the number of the credit card?"
)
print(str(response))
"""
Output:
The number of the credit card is 3714-<US_DRIVER_LICENSE_1>-47322.
"""
Mais il est également connu que tous les émetteurs de cartes de crédit ont des IIN (Issuer Identification Number) attribués. Les premiers chiffres définissent l’émetteur. Donc, dans ce cas, 37 signifie American Express. Si vous ne le savez pas, nous pouvons le vérifier en le demandant au modèle.
response = index.as_query_engine().query(
"What is the issuer of the credit card number?"
)
print(str(response))
The issuer of the credit card number is American Express
Ainsi, nous voyons que le modèle peut reconnaître l’émetteur de la carte, même si cette information n’a pas été fournie dans le texte. Cela signifie que le modèle a été entraîné avec des informations de cartes de crédit concernant les émetteurs et peut fournir la réponse grâce à ses connaissances. Il s’agit d’un exemple de violations de la confidentialité des données au stade de la génération, décrites ci-dessus.
Conclusion
Oz nous a guidés à travers les différentes étapes d’un pipeline RAG et a souligné où les préoccupations de sécurité peuvent être traitées. La première préoccupation clé concerne l’anonymisation des données, afin de garantir que les données sensibles ne puissent pas être consultées par des tiers non autorisés. Cependant, il est important de se rappeler que les modèles de fondation LLM ont pu être entraînés sur ces données, faisant des modèles eux-mêmes des sources potentielles de fuite de données.
Pour sécuriser l’accès aux données et leur transmission, le contrôle d’accès et le chiffrement sont essentiels. Ces techniques offrent un niveau élevé de sécurité et de contrôle, mais des menaces comme l’injection de prompt et la manipulation de recherche représentent encore des risques pour les informations sensibles.
Par conséquent, l’ajout de plusieurs couches de sécurité tout au long du pipeline est essentiel pour atténuer les menaces potentielles. Une application RAG prête pour la production doit intégrer des mesures de sécurité robustes à chaque étape afin de garantir que le système est résilient face aux attaques et conforme aux normes réglementaires.
Ressources supplémentaires
Continuer à lire

How Zilliz Saw the Future of Vector Databases—and Built for Production
An inside look at how Zilliz built vector databases for real-world use, focusing on scalability, stability, and running them reliably at scale.

Vector Databases vs. Document Databases
Use a vector database for similarity search and AI-powered applications; use a document database for flexible schema and JSON-like data storage.

Proactive Monitoring for Vector Database: Zilliz Cloud Integrates with Datadog
we're excited to announce Zilliz Cloud's integration with Datadog, enabling comprehensive monitoring and observability for your vectorDB deployments.



