E-06 Pipelines RAG
Brique E: Données, RAG, contexte, mémoire. Version anglaise: E-06-rag-pipelines
1. Rôle et responsabilités
Pipelines Haystack d'ingestion (découpage, DLP, embedding) et de requête (recherche vectorielle ou hybride, filtrage ACL, reranking optionnel).
- Embeddings par le Model Gateway (POST /v1/gateway/embeddings) avec le modèle d'embedding de la base de connaissances
- Recherche filtrée par ACL et clearance, mode
vectorouhybrid - Reranking optionnel via POST /v1/gateway/rerank
- Réindexation vers un autre modèle d'embedding, sans mélange de vecteurs
- Citations avec provenance
Chaque base de connaissances a un modèle d'embedding du registre (embedding_model, capacité embeddings) et une dimension, choisis à la création (défaut EAI_RAG_EMBEDDING_MODEL). Chaque appel d'embedding (segments d'un document, requête, réindexation) passe par les contrôles du Model Gateway : kill switch, plafond de classification et rétention du modèle, région, DLP, décision de politique model.invoke, garde de sortie, réservation de quota et Usage Event mesuré sur la réponse du fournisseur. Les segments partent avec la classification de leur document : un document au-dessus du plafond du modèle est refusé avant tout appel sortant.
Modèles livrés :
bge-m3-vllm: BAAI/bge-m3 servi par vLLM en mode embedding (1024 dimensions, français et anglais, plafondsecret, aucune rétention), seul modèle livré pour les données restricted et secret ;text-embedding-3-small: OpenAI (1536 dimensions, ou 256, 512 et 1024 avecdimensions), plafondconfidential;local-hash-256: hachage de mots et de trigrammes, sans modèle ni appel sortant, accepté en dev et en test seulement.
2. Position dans l'architecture et interactions
- Appelants: Agents (outil rag), SDK, Context Manager.
- Chemin d'exécution: Synchrone (ingestion et requête), asynchrone (réindexation par le worker).
- Toute interaction passe par l'API Control Plane v1 (
/v1) derrière la passerelle API (D-14).
3. Composant open source et partie développée
- Open source: Haystack
- Développé: Composants ACL, provenance, intégration passerelle, espaces d'embedding et réindexation.
- Intégration externe via un adaptateur
eai/integrations/<system>.pyavec repli in-process lorsque l'URL n'est pas configurée.
4. Modèle de données
Tables (schéma eai, RLS tenant_id):
eai.knowledge_bases(embedding_model,dimensions,vector_generation,vector_collection)eai.kb_documentseai.kb_chunks(generation,dimensionscontrôlée contre la taille du vecteur)eai.kb_reindex_jobs
Colonnes communes : id uuid, tenant_id uuid NOT NULL, created_at, updated_at ; politique RLS current_setting('app.tenant_id', true)::uuid.
5. Contrat
- Contrat appliqué: context-contract
- Schéma JSON:
contracts/v1/context-contract.schema.json - Champs clés:
segments[].source, segments[].provenance - Validation :
POST /v1/contracts/{name}/validate; application d'un manifeste :POST /v1/manifests/apply.
6. Endpoints API
GET /v1/knowledge-basesPOST /v1/knowledge-basesGET /v1/knowledge-bases/{id}DELETE /v1/knowledge-bases/{id}POST /v1/knowledge-bases/{id}/documentsGET /v1/knowledge-bases/{id}/documentsDELETE /v1/knowledge-bases/{id}/documents/{doc_id}POST /v1/knowledge-bases/{id}/queryPUT /v1/knowledge-bases/{id}/aclPOST /v1/knowledge-bases/{id}/reindexGET /v1/knowledge-bases/{id}/reindex-jobs
Requête POST /v1/knowledge-bases:
{
"name": "support",
"classification": "confidential",
"embedding_model": "bge-m3-vllm"
}
Requête POST /v1/knowledge-bases/{id}/query:
{
"query": "délai de remboursement",
"top_k": 5,
"mode": "hybrid",
"rerank": true,
"rerank_model": "rerank-v3-5"
}
Réponse:
{
"knowledge_base_id": "0b6f3c1e-9a52-4d7e-8c1a-2f4e6d8b0a13",
"query": "délai de remboursement",
"results": [
{
"chunk_id": "5d2a7e90-3c14-4b8f-a6d1-7e9b2c4f6a80",
"document_id": "a3c5e7f9-1b2d-4e6a-8c0e-2f4a6c8e0b1d",
"title": "Conditions de remboursement",
"ordinal": 3,
"content": "Le remboursement intervient sous 14 jours...",
"score": 0.82,
"vector_score": 0.79,
"keyword_score": 0.85,
"rerank_score": 0.91,
"classification": "internal",
"provenance": {
"source_type": "rag",
"source_id": "a3c5e7f9-1b2d-4e6a-8c0e-2f4a6c8e0b1d",
"version": "2",
"classification": "internal"
}
}
],
"count": 1,
"mode": "hybrid",
"reranked": true,
"warnings": [],
"embedding_model": "bge-m3-vllm"
}
Requête POST /v1/knowledge-bases/{id}/reindex (réponse 202 avec la tâche job_id, status, from, to, documents_total, exécutée par le job embeddings_reindex du worker) :
{
"embedding_model": "text-embedding-3-small",
"dimensions": 512
}
7. Exemples SDK
Python:
from enterprise_ai import EnterpriseAI
client = EnterpriseAI(base_url="<control-plane-url>", api_key="eai_xxx_secret")
kb = client.rag.create(name="support", chunk_size=800, embedding_model="bge-m3-vllm")
res = client.rag.query(kb.id, query="délai de remboursement", top_k=5, mode="hybrid")
TypeScript:
import { EnterpriseAI } from "@enterprise-ai/sdk";
const client = new EnterpriseAI({ baseUrl: "<control-plane-url>", apiKey: process.env.EAI_API_KEY });
const res = await client.knowledgeBases.query("kb_support", { query: "refund delay", top_k: 5 });
Java:
EnterpriseAIClient client = EnterpriseAIClient.builder()
.baseUrl("<control-plane-url>")
.apiKey(System.getenv("EAI_API_KEY"))
.build();
JsonNode res = client.knowledge().query("kb_support", Map.of("query", "refund delay", "top_k", 5));
Go:
c, _ := eai.NewClient(eai.WithBaseURL("<control-plane-url>"), eai.WithAPIKey(os.Getenv("EAI_API_KEY")))
res, _ := c.Knowledge.Query(ctx, "kb_support", map[string]any{"query": "refund delay", "top_k": 5})
8. Configuration
- Variables d'environnement:
EAI_RAG_EMBEDDING_MODEL,EAI_MEMORY_EMBEDDING_MODEL,EAI_RAG_RERANK_MODEL,EAI_EMBEDDINGS_BATCH_SIZE,EAI_WORKER_EMBEDDINGS_REINDEX_INTERVAL_SECONDS,EAI_QDRANT_URL,EAI_DATABASE_URL - Clés Helm:
qdrant.enabled - Modèle local : entrée
bge-m3devllm.models(option--task embedding) et entréebge-m3-vllmdelitellm.config.model_list(mode: embedding) dansvalues-onprem-gpu.yaml
9. Contrôles de sécurité
- Scope rag:query ; ACL appliquée avant retour, jamais après génération
- Classification > clearance -> chunk exclu
- Segments envoyés au modèle d'embedding avec la classification du document : au-dessus du plafond du modèle, 403
classification_exceededavant tout appel sortant - Clé du fournisseur injectée côté serveur par le gateway, jamais lue par la brique
- Toutes les requêtes portent le tenant issu du credential ; RLS PostgreSQL
- Chaque mutation et décision de politique écrit un événement d'audit chaîné
10. Observabilité
- Métriques Prometheus:
eai_rag_queries_total{outcome},eai_rag_retrieval_latency_seconds,eai_rag_embeddings_total{operation},eai_vector_search_latency_seconds{store} - Traces: spans OpenTelemetry avec conventions sémantiques GenAI (
gen_ai.operation.name,gen_ai.agent.id,gen_ai.tool.name), attributseai.tenant_id,eai.run_id, propagationtraceparent. - Actions d'audit:
knowledge.query,knowledge.document.ingest,knowledge_base.reindex.request,knowledge_base.reindex.complete,model.invoke(chaque appel d'embedding)
11. Unités FinOps
- Embeddings : un Usage Event
embeddingspar appel du gateway, avec le fournisseur, la région et les tokens mesurés du modèle de la base (labels.operation: ingest, query, reindex). - Requêtes : Usage Event
rag(retrieval_queries) ; reranking : Usage Eventreranking. - Émis comme Usage Event (
POST /v1/finops/usage) avec tenant, projet, agent et run.
12. Modes de défaillance et résilience
- Reranker indisponible, refusé ou non configuré : résultats dans l'ordre de la recherche,
reranked: falseet avertissementreranker_unavailable,rerank_refusedoureranker_not_configured - Vecteurs d'une autre taille renvoyés par le fournisseur : 502
embedding_dimension_mismatch; base vectorielle indisponible : 503vector_store_unavailable - Réindexation en échec : la génération précédente reste celle interrogée ; erreur transitoire (429, 502, 503, 504) retentée jusqu'à 3 fois
- Erreurs normalisées (enveloppe error, message_i18n en/fr)
13. Adoption autonome (client d'un client)
- enterprise_ai.rag + Control Plane + Qdrant.
- SDK:
enterprise_ai.privacy / dlp / knowledge_bases / memory / retention / lineage - Déploiement minimal : chart Helm avec
controlPlane.enabled=trueet PostgreSQL ; les composants externes désactivés utilisent leur repli in-process.
14. Tests d'acceptation
- Utilisateur sans ACL ne reçoit aucun chunk du document
- Suppression de document retire ses vecteurs
- Accès inter-tenant refusé
- Erreur renvoyée en fr avec Accept-Language: fr
- Document secret refusé par un modèle d'embedding plafonné à confidential, sans appel sortant
- Deux modèles d'embedding d'un même tenant ne mélangent jamais leurs vecteurs, réindexation comprise
RAG gouverné (kit L4)
RAG gouverné : découpage Haystack (haystack-ai, extra rag) quand la bibliothèque est installée, ACL document et fragment (chunk_readers) filtrées dans le magasin de vecteurs puis à nouveau avant le contexte, vérification du connecteur source (source_connector) à l'ingestion et à la requête, quarantaine des documents suspects (injection, texte caché, instructions anormales, embeddings aberrants) avec revue par le responsable des données (GET /v1/knowledge-bases/{id}/quarantine, POST .../documents/{doc_id}/review), citations avec version du document, URI source et position du fragment, cache sensible chiffré par tenant. Tests : tests/test_rag_governance.py.