Schutz sensibler und personenbezogener Daten in RAG mit Elasticsearch und LlamaIndex
Wie man sensible Daten und personenbezogene Daten in einer RAG-Anwendung mit Elasticsearch und LlamaIndex schützt.
In diesem Beitrag werden wir uns mit Möglichkeiten zum Schutz personenbezogener Daten (PII) und sensibler Daten bei der Verwendung öffentlicher LLMs in einem RAG-Ablauf (Retrieval Augmented Generation) befassen. Wir werden untersuchen, wie man personenbezogene Daten und sensible Daten mithilfe von Open-Source-Bibliotheken und regulären Ausdrücken maskieren kann, sowie wie man lokale LLMs verwendet, um Daten zu maskieren, bevor man einen öffentlichen LLM aufruft.
Bevor wir beginnen, wollen wir einige Begriffe wiederholen, die wir in diesem Beitrag verwenden.
Terminologie
LlamaIndex ist ein führendes Datenframework für die Entwicklung von LLM-Anwendungen (Large Language Model). LlamaIndex bietet Abstraktionen für verschiedene Phasen der Entwicklung einer RAG-Anwendung (Retrieval Augmented Generation). Frameworks wie LlamaIndex und LangChain bieten Abstraktionen, damit Anwendungen nicht eng an die APIs eines bestimmten LLM gekoppelt werden.
Elasticsearch wird von Elastic angeboten. Elastic ist ein Branchenführer hinter Elasticsearch, einem skalierbaren Datenspeicher und einer Vektordatenbank, die Volltextsuche für Präzision, Vektorsuche für semantisches Verständnis und Hybridsuche für das Beste aus beiden Welten unterstützt. Elasticsearch ist eine verteilte, RESTful-basierte Such- und Analyse-Engine, ein skalierbarer Datenspeicher und eine Vektordatenbank. Die in diesem Blog verwendeten Elasticsearch-Funktionen sind in der kostenlosen Open-Source-Version von Elasticsearch verfügbar.
Retrieval-Augmented Generation (RAG) ist eine KI-Technik bzw. ein KI-Muster, bei dem LLMs mit externem Wissen versorgt werden, um Antworten auf Benutzeranfragen zu generieren. Dadurch können die Antworten des LLM auf einen spezifischen Kontext zugeschnitten und weniger allgemein gehalten werden.
Einbettungen sind numerische Repräsentationen der Bedeutung von Texten/Medien. Es handelt sich um niedrigdimensionale Darstellungen hochdimensionaler Informationen.
RAG und Datenschutz
Im Allgemeinen sind große Sprachmodelle (LLMs) gut darin, Antworten auf der Grundlage von im Modell verfügbaren Informationen zu generieren, die mit Internetdaten trainiert werden können. Für Anfragen, bei denen die im Modell nicht verfügbaren Informationen vorliegen, müssen die LLMs jedoch externes Wissen oder spezifische Details erhalten, die nicht im Modell enthalten sind. Solche Informationen könnten sich in Ihrer Datenbank oder Ihrem internen Wissenssystem befinden. Retrieval-Augmented Generation (RAG) ist eine Technik, bei der für eine gegebene Benutzeranfrage zunächst relevante Kontextinformationen aus externen Systemen (z. B. Ihrer Datenbank) abgerufen und diese Kontextinformationen zusammen mit der Benutzeranfrage an das LLM gesendet werden, um eine spezifischere und relevantere Antwort zu generieren.
Dadurch eignet sich die RAG-Technik hervorragend für Anwendungen in der Fragebeantwortung, der Inhaltserstellung und überall dort, wo ein tiefes Verständnis von Kontext und Details von Vorteil ist.
Daher besteht bei einer RAG-Pipeline die Gefahr, dass interne Informationen wie PII (personenbezogene Daten) und sensible Informationen (z. B. Namen, Geburtsdaten, Kontonummern usw.) öffentlichen LLMs zugänglich gemacht werden.
Obwohl Ihre Daten bei der Verwendung einer Vektordatenbank wie Elasticsearch (durch verschiedene Mechanismen wie rollenbasierte Zugriffskontrolle, Dokumentensicherheit usw.) sicher sind, ist Vorsicht geboten, wenn Sie Daten an ein öffentliches LLM senden.
Der Schutz personenbezogener Daten (PII) und sensibler Daten ist bei der Verwendung großer Sprachmodelle (LLMs) aus mehreren Gründen von entscheidender Bedeutung:
Datenschutzkonformität: Viele Regionen verfügen über strenge Vorschriften, wie beispielsweise die Datenschutz-Grundverordnung (DSGVO) in Europa oder den California Consumer Privacy Act (CCPA) in den Vereinigten Staaten, die den Schutz personenbezogener Daten vorschreiben. Die Einhaltung dieser Gesetze ist notwendig, um rechtliche Konsequenzen und Geldstrafen zu vermeiden.
Nutzervertrauen: Die Gewährleistung der Vertraulichkeit und Integrität sensibler Informationen schafft Nutzervertrauen. Nutzer werden Systeme, von denen sie glauben, dass sie ihre Privatsphäre schützen, eher nutzen und mit ihnen interagieren.
Datensicherheit: Der Schutz vor Datenlecks ist unerlässlich. Werden sensible Daten LLMs ohne angemessene Sicherheitsvorkehrungen zugänglich gemacht, können sie gestohlen oder missbraucht werden, was zu potenziellen Schäden wie Identitätsdiebstahl oder Finanzbetrug führen kann.
Ethische Überlegungen: Aus ethischer Sicht ist es wichtig, die Privatsphäre der Nutzer zu respektieren und verantwortungsvoll mit ihren Daten umzugehen. Der unsachgemäße Umgang mit personenbezogenen Daten kann zu Diskriminierung, Stigmatisierung oder anderen negativen gesellschaftlichen Auswirkungen führen.
Unternehmensreputation: Unternehmen, die sensible Daten nicht schützen, können einen Reputationsschaden erleiden, der langfristige negative Auswirkungen auf ihr Geschäft haben kann, einschließlich Kunden- und Umsatzverlusten.
Reduzierung des Missbrauchsrisikos: Der sichere Umgang mit sensiblen Daten trägt dazu bei, einen missbräuchlichen Einsatz der Daten oder des Modells zu verhindern, wie beispielsweise das Trainieren der Modelle mit verzerrten Daten oder die Verwendung der Daten zur Manipulation oder Schädigung von Einzelpersonen.
Zusammenfassend lässt sich sagen, dass ein umfassender Schutz personenbezogener Daten und sensibler Daten notwendig ist, um die Einhaltung gesetzlicher Bestimmungen zu gewährleisten, das Vertrauen der Nutzer zu erhalten, die Datensicherheit sicherzustellen, ethische Standards einzuhalten, den Ruf des Unternehmens zu schützen und das Missbrauchsrisiko zu verringern.
Kurze Zusammenfassung
Im vorherigen Beitrag haben wir besprochen, wie man ein Q&A-Erlebnis mit einer RAG-Technik und Elasticsearch als Vektordatenbank unter Verwendung von LlamaIndex und einem lokal laufenden Mistral LLM implementiert. Hier bauen wir darauf auf.
Das Lesen des vorherigen Beitrags ist optional, da wir nun kurz besprechen/zusammenfassen werden, was wir im vorherigen Beitrag behandelt haben.
Wir verfügten über einen Beispieldatensatz mit Callcenter-Gesprächen zwischen Agenten und Kunden eines fiktiven Hausratversicherungsunternehmens. Wir haben eine einfache RAG-Anwendung entwickelt, die Fragen wie „Für welche Art von wasserbezogenen Problemen reichen Kunden Schadensmeldungen ein?“ beantwortet.
Im Großen und Ganzen sah der Ablauf so aus.

Während der Indexierungsphase haben wir Dokumente mithilfe der LlamaIndex-Pipeline geladen und indexiert. Die Dokumente wurden in Abschnitte unterteilt und zusammen mit ihren Einbettungen in der Elasticsearch-Vektordatenbank gespeichert.
Während der Abfragephase, als der Benutzer eine Frage stellte, ermittelte LlamaIndex die K ähnlichsten Dokumente, die für die Abfrage relevant waren. Diese Top-K relevanten Dokumente wurden zusammen mit der Anfrage an das lokal laufende Mistral LLM gesendet, das dann die Antwort generierte, die an den Benutzer zurückgesendet wurde. Sie können sich gerne den vorherigen Beitrag durchlesen oder den Code erkunden.
Im vorherigen Beitrag hatten wir LLM lokal am Laufen. Im Produktionsbetrieb kann es jedoch sinnvoll sein, ein externes LLM von verschiedenen Anbietern wie OpenAI, Mistral, Anthropic usw. zu verwenden. Es könnte daran liegen, dass Ihr Anwendungsfall ein größeres Basismodell erfordert oder dass eine lokale Ausführung aufgrund von Anforderungen der Unternehmensproduktion wie Skalierbarkeit, Verfügbarkeit, Leistung usw. nicht möglich ist.
Die Einbindung eines externen LLM in Ihre RAG-Pipeline birgt das Risiko, dass sensible Daten und personenbezogene Daten unbeabsichtigt an die LLMs gelangen. In diesem Beitrag werden wir Möglichkeiten zur Maskierung personenbezogener Daten im Rahmen Ihres RAG-Prozesses untersuchen, bevor Sie Dokumente an einen externen LLM senden.
RAG mit einem öffentlichen LLM
Bevor wir darauf eingehen, wie Sie Ihre personenbezogenen Daten und sensiblen Informationen in einer RAG-Pipeline schützen können, werden wir zunächst eine einfache RAG-Anwendung mit LlamaIndex, der Elasticsearch Vector-Datenbank und OpenAI LLM erstellen.
Voraussetzungen
Wir benötigen Folgendes.
Elasticsearch ist als Vektordatenbank zum Speichern der Einbettungen eingerichtet und betriebsbereit. Folgen Sie den Anweisungen aus dem vorherigen Beitrag zur Installation von Elasticsearch.
OpenAI-API-Schlüssel.
Einfache RAG-Anwendung
Zur Information: Der vollständige Code befindet sich in diesem GitHub-Repository(Branch:protecting-pii). Das Klonen des Repositorys ist optional, da wir den Code im Folgenden genauer betrachten werden.
Erstellen Sie in Ihrer bevorzugten IDE eine neue Python-Anwendung mit den folgenden 3 Dateien.
index.pyHierhin wird der Code für die Indizierung von Daten eingefügt.query.pyHier wird der Code für Abfragen und die Interaktion mit LLM eingefügt..envdort, wo Konfigurationseigenschaften wie API-Schlüssel gespeichert werden.
Wir müssen einige Pakete installieren. Wir beginnen damit, eine neue virtuelle Python-Umgebung im Stammverzeichnis Ihrer Anwendung zu erstellen.
python3 -m venv .venvAktivieren Sie die virtuelle Umgebung und installieren Sie die unten aufgeführten erforderlichen Pakete.
source .venv/bin/activate
pip install llama-index
pip install llama-index-embeddings-openai
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
pip install openaiKonfigurieren Sie die Verbindungseigenschaften von OpenAI und Elasticsearch in der .env-Datei. Datei.
OPENAI_API_KEY="REPLACEME"
ELASTIC_CLOUD_ID="REPLACEME"
ELASTIC_API_KEY="REPLACEME"Indexierungsdaten
Laden Sie die Datei conversations.json herunter, die Konversationen zwischen Kunden und Callcenter-Mitarbeitern unseres fiktiven Hausversicherungsunternehmens enthält. Platzieren Sie die Datei im Stammverzeichnis der Anwendung zusammen mit den beiden Python-Dateien und der .env-Datei. die Datei, die Sie zuvor erstellt haben. Nachfolgend ein Beispiel für den Inhalt der Datei.
{
"conversation_id": 103,
"customer_name": "Sophia Jones",
"agent_name": "Emily Wilson",
"policy_number": "JKL0123",
"conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
"summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}Fügen Sie den unten stehenden Code in index.py ein, der sich um die Indizierung der Daten kümmert.
# index.py
# pip install sentence-transformers
# pip install llama-index-embeddings-openai
# pip install llama-index-embeddings-huggingface
import json
import os
from dotenv import load_dotenv
from llama_index.core import Document
from llama_index.core import Settings
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore
def get_documents_from_file(file):
"""Reads a json file and returns list of Documents"""
with open(file=file, mode='rt') as f:
conversations_dict = json.loads(f.read())
# Build Document objects using fields of interest.
documents = [Document(text=item['conversation'],
metadata={"conversation_id": item['conversation_id']})
for
item in conversations_dict]
return documents
# Load .env file contents into env
load_dotenv('.env')
Settings.embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-small-en-v1.5"
)
def main():
# ElasticsearchStore is a VectorStore that
# takes care of Elasticsearch Index and Data management.
es_vector_store = ElasticsearchStore(index_name="convo_index",
vector_field='conversation_vector',
text_field='conversation',
es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
es_api_key=os.getenv("ELASTIC_API_KEY"))
# LlamaIndex Pipeline configured to take care of chunking, embedding
# and storing the embeddings in the vector store.
llamaindex_pipeline = IngestionPipeline(
transformations=[
SentenceSplitter(chunk_size=350, chunk_overlap=50),
Settings.embed_model
],
vector_store=es_vector_store
)
# Load data from a json file into a list of LlamaIndex Documents
documents = get_documents_from_file(file="conversations.json")
llamaindex_pipeline.run(documents=documents)
print(".....Indexing Data Completed.....\n")
if __name__ == "__main__":
main()Wenn Sie den obigen Code ausführen, wird ein Index in Elasticsearch erstellt und die Einbettungen werden im Elasticsearch-Index mit dem Namen convo_index gespeichert.
Falls Sie eine Erläuterung zur LlamaIndex IngestionPipeline benötigen, lesen Sie bitte den vorherigen Beitrag im Abschnitt "IngestionPipeline erstellen".
Abfrage
Im vorherigen Beitrag haben wir ein lokales LLM für Abfragen verwendet.
In diesem Beitrag verwenden wir das öffentliche LLM OpenAI, wie unten dargestellt.
# query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.llms.openai import OpenAI
from index import es_vector_store
# Public LLM where we send user query and Related Documents
llm = OpenAI()
index = VectorStoreIndex.from_vector_store(es_vector_store)
# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are sent as-is. So any PII/Sensitive data is sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10)
query="Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)Der obige Code gibt die Antwort von OpenAI wie folgt aus.
Kunden haben verschiedene Ansprüche im Zusammenhang mit Wasser geltend gemacht, darunter Probleme wie Wasserschäden in Kellern, geplatzte Rohre, Hagelschäden an Dächern sowie die Ablehnung von Ansprüchen aufgrund von Gründen wie mangelnder rechtzeitiger Meldung, Wartungsmängeln, allmählichem Verschleiß und bereits bestehenden Schäden. In allen Fällen äußerten die Kunden ihre Frustration über die Ablehnung ihrer Ansprüche und forderten eine faire Bewertung und Entscheidung in Bezug auf ihre Ansprüche.
Maskierung von PII in RAG
Was wir bisher behandelt haben, beinhaltet das Senden von Dokumenten unverändert zusammen mit der Benutzeranfrage an OpenAI.
In der RAG-Pipeline haben wir, nachdem der relevante Kontext aus einem Vektorspeicher abgerufen wurde, die Möglichkeit, personenbezogene Daten und sensible Informationen zu maskieren, bevor wir die Anfrage und den Kontext an das LLM senden.
Es gibt verschiedene Möglichkeiten, personenbezogene Daten zu maskieren, bevor man sie an ein externes LLM sendet, wobei jede ihre eigenen Vorzüge hat. Wir betrachten einige der folgenden Optionen.
Verwendung von NLP-Bibliotheken wie spacy.io oder Presidio (Open-Source-Bibliothek, die von Microsoft gepflegt wird).
Verwendung von LlamaIndex direkt aus der Verpackung
NERPIINodePostprocessor.Nutzung lokaler LLMs über
PIINodePostprocessor
Sobald Sie die Maskierungslogik mithilfe einer der oben genannten Methoden implementiert haben, können Sie die LlamaIndex IngestionPipeline mit einem PostProcessor konfigurieren (entweder mit einem eigenen benutzerdefinierten PostProcessor oder mit einem der standardmäßig verfügbaren PostProcessors von LlamaIndex).
Verwendung von NLP-Bibliotheken
Im Rahmen der RAG-Pipeline könnten wir sensible Daten mithilfe von NLP-Bibliotheken maskieren. In dieser Demo verwenden wir das spacy.io-Paket.
Erstellen Sie eine neue Datei query_masking_nlp.py und fügen Sie den unten stehenden Code ein.
# query_masking_nlp.py
# pip install spacy
# python3 - m spacy download en_core_web_sm
import re
from typing import List, Optional
import spacy
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor.types import BaseNodePostprocessor
from llama_index.core.schema import NodeWithScore
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store
# Load the spaCy model
nlp = spacy.load("en_core_web_sm")
# Compile regex patterns for performance
phone_pattern = re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b')
email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
date_pattern = re.compile(r'\b(\d{1,2}[-/]\d{1,2}[-/]\d{2,4}|\d{2,4}[-/]\d{1,2}[-/]\d{1,2})\b')
dob_pattern = re.compile(
r"(January|February|March|April|May|June|July|August|September|October|November|December)\s(\d{1,2})(st|nd|rd|th),\s(\d{4})")
address_pattern = re.compile(r'\d+\s+[\w\s]+\,\s+[A-Za-z]+\,\s+[A-Z]{2}\s+\d{5}(-\d{4})?')
zip_code_pattern = re.compile(r'\b\d{5}(?:-\d{4})?\b')
policy_number_pattern = re.compile(r"[A-Z]{3}\d{4}\.$") # 3 characters followed by 4 digits, in our case e.g XYZ9876
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
# match = re.match(policy_number_pattern, "XYZ9876")
# print(match)
def mask_pii(text):
"""
Masks Personally Identifiable Information (PII) in the given
text using pre-defined regex patterns and spaCy's named entity recognition.
Args:
text (str): The input text containing potential PII.
Returns:
str: The text with PII masked.
"""
# Process the text with spaCy for NER
doc = nlp(text)
# Mask entities identified by spaCy NER (e.g First/Last Names etc)
for ent in doc.ents:
if ent.label_ in ["PERSON", "ORG", "GPE"]:
text = text.replace(ent.text, '[MASKED]')
# Apply regex patterns after NER to avoid overlapping issues
text = phone_pattern.sub('[PHONE MASKED]', text)
text = email_pattern.sub('[EMAIL MASKED]', text)
text = date_pattern.sub('[DATE MASKED]', text)
text = address_pattern.sub('[ADDRESS MASKED]', text)
text = dob_pattern.sub('[DOB MASKED]', text)
text = zip_code_pattern.sub('[ZIP MASKED]', text)
text = policy_number_pattern.sub('[POLICY MASKED]', text)
return text
class CustomPostProcessor(BaseNodePostprocessor):
"""
Custom Postprocessor which masks Personally Identifiable Information (PII).
PostProcessor is called on the Documents before they are sent to the LLM.
"""
def _postprocess_nodes(
self, nodes: List[NodeWithScore], query_bundle: Optional[QueryBundle]
) -> List[NodeWithScore]:
# Masks PII
for n in nodes:
n.node.set_content(mask_pii(n.text))
return nodes
# Use Public LLM to send user query and Related Documents
llm = OpenAI()
index = VectorStoreIndex.from_vector_store(es_vector_store)
# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are masked based on custom logic defined in CustomPostProcessor._postprocess_nodes.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[CustomPostProcessor()])
query = "Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)Die Antwort des LLM ist unten dargestellt.
Kunden haben verschiedene Ansprüche im Zusammenhang mit Wasser geltend gemacht, darunter Probleme wie Wasserschäden in Kellern, geplatzte Rohre, Hagelschäden an Dächern und Überschwemmungen bei Starkregen. Diese Ansprüche haben zu Frustrationen geführt, da Ansprüche aus Gründen wie mangelnder rechtzeitiger Meldung, Wartungsproblemen, allmählichem Verschleiß und bereits vorhandenen Schäden abgelehnt wurden. Kunden äußerten Enttäuschung, Stress und finanzielle Belastung infolge dieser Ablehnungen ihrer Ansprüche und forderten faire Bewertungen und gründliche Überprüfungen. Einige Kunden sahen sich zudem mit Verzögerungen bei der Schadensregulierung konfrontiert, was zu weiterer Unzufriedenheit mit dem Service der Versicherungsgesellschaft führte.
Im obigen Code geben wir beim Erstellen der Llama Index QueryEngine einen CustomPostProcessor an.
Die Logik, die von der QueryEngine aufgerufen wird, ist in der Methode _postprocess_nodes von CustomPostProcessor definiert. Wir verwenden die SpaCy.io-Bibliothek, um benannte Entitäten in unseren Daten zu erkennen, und verwenden dann einige reguläre Ausdrücke, um diese Namen sowie sensible Informationen zu ersetzen, bevor wir die Dokumente an das LLM senden.
Nachfolgend finden Sie beispielhaft Ausschnitte aus den Originalkonversationen und der vom CustomPostProcessor erstellten maskierten Konversation.
Originaltext:
Kunde: Hallo, ich bin Matthew Lopez, geboren am 12. Oktober 1984, und wohne in 456 Cedar St, Smalltown, NY 34567. Meine Versicherungsnummer lautet TUV8901. Agent: Guten Tag, Matthew. Wie kann ich Ihnen heute behilflich sein? Kunde: Hallo, ich bin äußerst enttäuscht über die Entscheidung Ihres Unternehmens, meinen Antrag abzulehnen.
Maskierter Text durch den CustomPostProcessor.
Kunde: Hallo, ich bin [MASKED], [MASKED] ist [DOB MASKED], und ich wohne in der Cedar St 456, [MASKED], [MASKED] 34567. Meine Versicherungsnummer lautet [MASKED]. Agent: Guten Tag, [MASKE]. Wie kann ich Ihnen heute behilflich sein? Kunde: Hallo, ich bin äußerst enttäuscht über die Entscheidung Ihres Unternehmens, meinen Antrag abzulehnen.
Notiz:
Das Identifizieren und Maskieren von personenbezogenen Daten und sensiblen Informationen ist keine einfache Aufgabe. Die Berücksichtigung verschiedener Formate und Semantiken sensibler Informationen erfordert ein gutes Verständnis Ihres Fachgebiets und Ihrer Daten. Auch wenn der oben dargestellte Code für einige Anwendungsfälle funktionieren mag, müssen Sie ihn möglicherweise an Ihre Bedürfnisse und Tests anpassen.
Verwendung des LlamaIndex direkt aus der Verpackung NERPIINodePostprocessor
LlamaIndex hat den Schutz personenbezogener Daten in einer RAG-Pipeline durch die Einführung vereinfacht. NERPIINodePostprocessor.
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
# Use Public LLM to send user query and Related Documents
llm = OpenAI()
ner_processor = NERPIINodePostprocessor()
index = VectorStoreIndex.from_vector_store(es_vector_store)
# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents masked using the NERPIINodePostprocessor so that PII/Sensitive data is not sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[ner_processor])
query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)Die Antwort sieht wie folgt aus:
Kunden haben im Zusammenhang mit Bränden Schadensansprüche an ihren Immobilien geltend gemacht. In einem Fall wurde ein Anspruch auf Schadensersatz für einen Brandschaden an einer Garage abgelehnt, da Brandstiftung vom Versicherungsschutz ausgeschlossen ist. Ein anderer Kunde reichte eine Schadensmeldung wegen eines Brandschadens an seinem Haus ein, der durch seine Versicherungspolice abgedeckt war. Darüber hinaus meldete ein Kunde einen Küchenbrand und erhielt die Zusicherung, dass der Brandschaden abgedeckt sei.
Nutzung lokaler LLMs über PIINodePostprocessor
Alternativ könnten wir auch ein lokal oder in Ihrem privaten Netzwerk laufendes LLM nutzen, um die Maskierung durchzuführen, bevor die Daten an ein öffentliches LLM gesendet werden.
Wir werden Mistral, das auf Ollama auf Ihrem lokalen Rechner läuft, für die Maskierung verwenden.
Mistral lokal ausführen
Laden Sie Ollama herunter und installieren Sie es. Nach der Installation von Ollama führen Sie diesen Befehl aus, um Mistralherunterzuladen und auszuführen.
ollama run mistralDas Herunterladen und erstmalige lokale Ausführen des Modells kann einige Minuten dauern. Prüfen Sie, ob Mistral weht, indem Sie eine Frage wie die folgende stellen: „Schreibe ein Gedicht über Wolken“ und prüfen Sie, ob Ihnen das Gedicht gefällt. Bitte lassen Sie ollama laufen, da wir später über Code mit dem Mistral-Modell interagieren müssen.
Erstellen Sie eine neue Datei namens query_masking_local_LLM.py und fügen Sie den unten stehenden Code ein.
# pip install llama-index-llms-ollama
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import PIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.llms.openai import OpenAI
from index import es_vector_store
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
# Use Public LLM to send user query and Related Documents and Local LLM to mask
public_llm = OpenAI()
local_llm = Ollama(model="mistral")
pii_processor = PIINodePostprocessor(llm=local_llm)
index = VectorStoreIndex.from_vector_store(es_vector_store)
# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the public LLM.
# Note that documents are masked using the local llm via PIINodePostprocessor
# so that PII/Sensitive data is not sent to the public LLM.
query_engine = index.as_query_engine(public_llm, similarity_top_k=10, node_postprocessors=[pii_processor])
query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)Die Antwort sieht in etwa so aus wie unten dargestellt.
Kunden haben im Zusammenhang mit Bränden Schadensansprüche an ihren Immobilien geltend gemacht. In einem Fall wurde ein Anspruch auf Schadensersatz für einen Brandschaden an einer Garage abgelehnt, da Brandstiftung vom Versicherungsschutz ausgeschlossen ist. Ein anderer Kunde reichte eine Schadensmeldung wegen eines Brandschadens an seinem Haus ein, der durch seine Versicherungspolice abgedeckt war. Darüber hinaus meldete ein Kunde einen Küchenbrand und erhielt die Zusicherung, dass der Brandschaden abgedeckt sei.
Fazit
In diesem Beitrag haben wir gezeigt, wie Sie personenbezogene Daten und sensible Daten beim Einsatz öffentlicher LLMs in einem RAG-Flow schützen können. Wir haben verschiedene Wege aufgezeigt, wie dies erreicht werden kann. Es wird dringend empfohlen, diese Ansätze anhand Ihres Anwendungsfalls und Ihrer Bedürfnisse zu testen, bevor Sie sie übernehmen.




