Aller au contenu

Intégration LlamaIndex

Vous voulez un RAG LlamaIndex où ni le fournisseur d'embeddings ni le LLM ne voient de données confidentielles. piighost fournit deux composants. PIINodeAnonymizer est une transformation d'ingestion qui dé-identifie chaque node avant l'embedding. PIIQueryEngine enveloppe le moteur de requête, dé-identifie la requête et restaure la réponse. Les deux partagent un pipeline de conversation, donc une valeur garde le même jeton à travers le corpus et la requête.

Pour la même idée orchestrée à la main sur un flux RAG simple, voir le script examples/langchain/rag.py. Cette page emballe cette idée en objets LlamaIndex réutilisables.

1. Construire le pipeline de conversation

Le pipeline dé-identifie et restaure sur une conversation dédiée au corpus. Ici un ExactMatchDetector garde l'exemple déterministe. Remplacez-le par un détecteur à modèle pour du vrai texte.

from piighost.components.detector import ExactMatchDetector
from piighost.pipeline import ThreadAnonymizationPipeline

THREAD = "docs"
detector = ExactMatchDetector({"Patrick": "PERSON", "Paris": "LOCATION"})
pipeline = ThreadAnonymizationPipeline(detector)

2. Dé-identifier à l'ingestion, avant l'embedding

Placez PIINodeAnonymizer dans les transformations avant le modèle d'embedding, pour que l'index soit bâti sur des jetons et que le fournisseur d'embeddings ne voie jamais de données confidentielles.

from llama_index.core import Document, Settings, VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.openai import OpenAIEmbedding

from piighost.integrations.llama_index import PIINodeAnonymizer

Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
anonymizer = PIINodeAnonymizer(pipeline=pipeline, thread_id=THREAD)
index = VectorStoreIndex.from_documents(
    [Document(text="Patrick lives in Paris.")],
    transformations=[SentenceSplitter(), anonymizer],
)

3. Envelopper le moteur de requête

PIIQueryEngine dé-identifie la requête dans la même conversation que le corpus, et restaure la réponse pour l'utilisateur. La recherche porte donc sur le corpus dé-identifié.

from llama_index.llms.openai import OpenAI

from piighost.integrations.llama_index import PIIQueryEngine

Settings.llm = OpenAI(model="gpt-5.6-terra")
engine = PIIQueryEngine(
    inner=index.as_query_engine(),
    pipeline=pipeline,
    thread_id=THREAD,
)
answer = engine.query("Where does Patrick live?")
print(answer.response)

La réponse est restaurée pour l'affichage. Sa formulation dépend du modèle, par exemple :

Patrick lives in Paris.

Le LLM a répondu sur <<PERSON:1>> et <<LOCATION:1>>. L'utilisateur voit Patrick et Paris restaurés. La recherche tourne sur le texte dé-identifié. Il y perd un peu de qualité, en échange de quoi les données confidentielles restent hors de l'appel d'embedding.

Voir aussi

  • Intégration LangChain : dé-identifier un agent LangChain avec le middleware.
  • Roadmap : ce qui est prévu par ailleurs.
  • Le script exécutable est dans examples/llama_index/rag.py.