Voir aussi : ADR-002 — Tool abstractions shared kernel · ADR-003 — Shared kernels secondaires · ADR-004 — Jumeaux de nommage scripting · Retour à l'index
ADR-006 — Sous-système RAG : shared kernel Rag.Abstractions et câblage DI Rag
Statut : Accepté · Date : 2026-07 · Portée : Orkeon.Application → Orkeon.Rag.Abstractions ; Orkeon.Infrastructure → Orkeon.Rag
Contexte
Le RAG est promu de Orkeon.Infrastructure/Knowledge +
Orkeon.Application/{Interfaces/Rag,Rag} vers un sous-système de premier rang src/rag/, sur le
modèle éprouvé de src/analysis/ (RaggableTree — voir
ADR-003) :
src/rag/Orkeon.Rag.Abstractions— contrats, DTOs et options (IChunkingStrategy,IDocumentLoader,IDocumentStore,IQueryTransformer,IReranker,IRetrievalEvaluator,IGroundednessChecker,IQueryComplexityClassifier,IIngestionPipeline,IRagPipeline,RagAnswer…). Dépend uniquement deOrkeon.Domain.src/rag/Orkeon.Rag— implémentations (chunkers, loaders, retrieval, reranking, ingestion, évaluation) et factories par nom.src/tools/Orkeon.Tools.Rag— tools agents (rag_search,rag_ingest,rag_eval), dans la familleTools.*conformément à ADR-004 (Orkeon.Tools.Rag, pasOrkeon.Rag.Tools).
Deux couplages transversaux à l'oignon sont nécessaires pour brancher le sous-système au cœur, exactement comme pour RaggableTree. Cet ADR les acte par anticipation : le squelette de projets et les contrats arrivent d'abord (RAG-02 / C1-C2) ; les références ci-dessous sont ajoutées par les lots de migration suivants.
Orkeon.Application → Orkeon.Rag.Abstractions— la couche Application a besoin des ports RAG (p. ex.IRagPipelinepour l'injection de connaissances crew/agent) sans voir la moindre implémentation.Orkeon.Infrastructure → Orkeon.Rag(concret, pas seulement les abstractions) — exclusivement comme câblage de composition confiné à un seul fichier DI (DependencyInjection/RagInfrastructureExtensions.cs, miroir deRaggableTreeInfrastructureExtensions.cs), notamment pour envelopper les appels d'embedding dansLlmLoggingDelegatingHandler.
Décision
Orkeon.Rag.Abstractionsest un shared kernel secondaire (même statut queTools.Abstractionsdans ADR-002 etAnalysis.Abstractionsdans ADR-003) : un projet d'abstractions ne dépendant que deDomain, donc consommable parApplicationsans cycle ni inversion du sens des dépendances.- La référence concrète
Infrastructure → Orkeon.Ragest acceptée comme câblage de composition localisé dans un seul fichier d'extensions DI ; l'Infrastructure assume son rôle de racine de composition pour le sous-système RAG.AddOrkeonRag()est un opt-in explicite (auto-suffisant,TryAdd*partout — l'hôte gagne), jamais appelé inconditionnellement depuisAddOrkeonInfrastructure. - Identité de types pour les plugins :
Orkeon.Rag.Abstractionsfigure dansOrkeonPluginsOptions.SharedAssemblyPrefixespour que les rerankers/chunkers/loaders fournis par des plugins gardent une identité de type unique à travers les frontières d'AssemblyLoadContext.
Conséquences
- Positif : les contrats RAG gagnent la visibilité d'un RaggableTree, un opt-in propre et l'extensibilité plugins ; les couplages sont traçables et contestables au lieu d'être renégociés à chaque revue.
- Vigilance :
Orkeon.Rag.Abstractionsdoit continuer à ne dépendre que deOrkeon.Domain— garanti partests/rag/Orkeon.Rag.Abstractions.Tests/ArchitectureTests.cs. Toute extension de l'usage concret d'Orkeon.Ragdans l'Infrastructure au-delà du fichier DI unique doit rouvrir cet ADR. - Rupture : les anciens namespaces (
Orkeon.Application.Interfaces.Rag.*,Orkeon.Application.Rag.*,Orkeon.Infrastructure.Knowledge.*) sont supprimés sans shims (rupture assumée, version0.9.x-beta; table de migration auCHANGELOG.md). Fait en RAG-02/C5 (2026-07-25) —rag_searchvit désormais dansOrkeon.Tools.Rag(RagSearchTool+AddOrkeonRagTools()), et l'opt-in du sous-système estAddOrkeonRag(configuration)dansOrkeon.Rag.DependencyInjection.
Amendement — 2026-07-25 (RAG-02/C3)
Le lot de migration qui porte les implémentations dans Orkeon.Rag ajoute deux couplages
sortants du projet concret Orkeon.Rag (jamais d'Orkeon.Rag.Abstractions, dont la
règle « Domain uniquement » reste inchangée) :
Orkeon.Rag → Orkeon.Application—Orkeon.Ragest un projet d'implémentation de l'anneau externe (même anneau qu'Orkeon.Infrastructure) et consomme directement les ports Application :Orkeon.Application.Interfaces.Ports.IEmbeddingProvider(interface d'embedding canonique, plan §4.1) pour les pipelines d'ingestion/requête, et les contrats de validationOrkeon.Application.Interfaces.Security(IDataValidator,IProvenanceTracker,DataValidationResult…) pour la validation du chemin d'ingestion. Le sens de l'oignon est respecté (anneau externe → Application) et aucun cycle n'apparaît :Applicationne référence queRag.Abstractions, jamaisOrkeon.Rag.Orkeon.Rag → Orkeon.Analysis.Abstractions— hébergeAnalysisEmbeddingProviderAdapter(sorti d'Orkeon.Infrastructure/LLMs/Embeddings/), le pont entre l'abstraction d'embedding Analysis et le port Application (« dansOrkeon.Rag, qui référence les deux mondes », plan §4.1).
Point de vigilance : outre le fichier de câblage DI, Orkeon.Infrastructure utilise aussi
Orkeon.Rag.Embeddings.AnalysisEmbeddingProviderAdapter depuis
LLMs/Embeddings/DefaultEmbeddingProviderResolver.cs — logique de résolution de composition
invoquée par AddOrkeonInfrastructure. C'est accepté au titre du rôle de racine de
composition ; tout usage d'Orkeon.Rag depuis du code runtime (hors composition) de
l'Infrastructure exige toujours de rouvrir cet ADR.
Amendement — 2026-07-26 (RAG-06)
La phase corrective superpose quatre décisions à cet ADR sans toucher à ses règles
de dépendance (Orkeon.Rag.Abstractions reste Domain-only — vérifié par les
ArchitectureTests) :
- CRAG sur le
StateGraphdu Domain, pas une boucle maison.CorrectiveRagPipeline(src/rag/Orkeon.Rag/Corrective/) est construit surStateGraph<RagGraphState>(Orkeon.Domain.Graph) — le même mode d'orchestration Graph que les crews — avec des arêtes conditionnelles sur le verdict de récupération (Correct|Incorrect|Ambiguous) et une double borne :Orkeon:Rag:Corrective:MaxIterationsplus le circuit breaker propre au graphe, dérivé de cette borne. L'épuisement dégrade en réponse best-effort ; le graphe ne lève jamais vers l'appelant. - Split du repli web : politique vs transport. Deux interrupteurs
indépendants, désactivés par défaut :
Orkeon:Rag:Corrective:WebFallback(la politique — le graphe a-t-il le droit de sortir du store local ; vit dansOrkeon.Rag.Abstractions, Domain+BCL uniquement) etOrkeon:Rag:WebFallback(le transport —WebSearchRetrieverOptions, endpoint SearxNG ; vit dansOrkeon.Rag, carSuspiciousActionet les préoccupations HTTP violeraient la règle de dépendance des Abstractions). Les deux doivent être activés pour que le nœudweb_fallbacks'exécute, et chaque page téléchargée passe parPromptInjectionDocumentValidatoravant d'entrer dans le working set. - Profil
correctivesans étage de rerank linéaire. Le preset désactive à dessein le cross-encoder ONNX et l'étage linéaire de groundedness : le graphe corrige en bouclant (evaluate → rewrite/refine → re-retrieve) et possède son nœud natifcheck_groundedness. La routeIterativedu profiladaptivedélègue àcorrective(le repli provisoire RAG-05 versqualityest levé). - Pas de
rag-adr.mdséparé. Le lot RAG-06 garde délibérément le registre de décisions ici (un seul ADR, amendé par phase) au lieu d'ajouter la pagedocs/architecture/rag-adr.mdesquissée par la fiche — un second document de décisions dupliquerait celui-ci et élargirait la dette de parité FR. Le guide d'architecture narratif estdocs/architecture/rag-pipeline.md.