Bundle produit doc-IA — reference
Nature du composant
Ce composant est un bundle Symfony (type symfony-bundle, autoload PSR-4 vers src/), destine a etre installe via Composer dans une application Symfony hote. Ce n'est pas une application : il n'expose ni controleur, ni route, ni template. Il fournit des services metier, des entites Doctrine et des commandes console ; l'application hote cable l'UI et la persistance.
- Point d'entree : une classe bundle qui etend
AbstractBundleet dont l'unique responsabilite est d'importer le fichier de wiring DI (config/services.php). - Pas de configuration semantique : aucun arbre de configuration de bundle dedie. Toute la configuration passe par des variables d'environnement injectees via
#[Autowire]sur les services. - Wiring DI :
autowire+autoconfigureactives ; chargement de toutsrc/en excluant la classe bundle,Entity/etContract/(entites et interface de contrat ne sont pas des services). - Cible de plateforme : PHP recent, composants Symfony et Doctrine ORM en versions majeures courantes (contraintes exactes hors perimetre de cette fiche).
Les quatre domaines fonctionnels
Le composant regroupe quatre surfaces produit autour de la documentation assistee par IA.
- Veille — veille technique agentique : collecte de sources (RSS/Atom), deduplication, classification par mots-cles, resume par LLM, ecriture d'une proposition Markdown, suivi de lecture par utilisateur.
- Chat — assistant documentaire RAG : recuperation de passages pertinents dans un index (via un bundle RAG externe), garde-fou hors-perimetre, generation LLM, reponse sourcee.
- Docs — acces en lecture au corpus documentaire clone, gestion du clone git (checkout d'un ref), re-indexation RAG lancee en tache de fond.
- Metrics — observabilite de la consommation de l'API du fournisseur LLM (usage tokens + cout) via son Admin API, analytics derives, alertes de cout par e-mail.
Un service de reglages applicatifs cle/valeur (fourni par une dependance externe) est consomme pour poser verrous et horodatages de taches de fond. Ce n'est pas un domaine implemente par le bundle.
Dependances sortantes (couplage inter-bundles)
- Bundle RAG externe — coeur RAG. Le composant consomme son service de recuperation et son modele de resultat (Chat), son service d'ingestion (commandes Docs) et le parametre de chemin d'index injecte dans les commandes.
- Bundle utilitaire externe — fournit le service de reglages cle/valeur utilise par les commandes Docs.
- Composants Symfony directs : client HTTP (appels LLM/Admin API, collecte, fetch), messenger + scheduler (cycle veille + synchro metriques), mailer + Twig (alertes e-mail), validator (contraintes), process (operations git), console, doctrine-bridge (
resolve_target_entities).
Architecture interne (modules)
src/ Chat/ assistant RAG (service, client LLM, settings, DTOs) Command/ commandes console (veille, metrics, docs) Contract/ interface de couplage utilisateur (decouplage app) Docs/ bibliotheque de lecture, gestion du clone git, lanceurs Entity/ entites Doctrine auto-mappees Metrics/ sync Admin API, analytics, alertes, client, messages Repository/ repositories Doctrine (listing / curation / agregation) Veille/ pipeline (collecte, fetch, classification, resume, ecriture...)
Patterns transverses :
- Ports & adapters : chaque etape lourde est derriere une interface, ce qui permet le stub de test et le remplacement d'implementation sans toucher l'orchestration.
- Decouverte par tag : les collecteurs, summarizers et classifiers sont auto-tagges ; un registre recoit toutes les implementations via iterateur autowire et dispatche selon le type de source.
- DTOs immuables (
readonly) pour le transport ; un accumulateur mutable de diagnostic est concu pour survivre a une reinitialisation de l'EntityManager. - Resilience worker long-running : le service de traitement ne charge que des IDs, recharge chaque entite depuis un EntityManager re-ouvert si necessaire, et isole les echecs item par item.
Contrats publics
Contrat implemente par l'application hote
Une interface de « lecteur de veille » expose une seule methode d'identifiant :
interface VeilleReaderInterface { public function getId(): ?int; }
- L'entite utilisateur de l'application l'implemente.
- Elle est resolue vers l'entite concrete via
doctrine.orm.resolve_target_entities. - L'entite de lecture pointe vers cette interface (ManyToOne, suppression en cascade). Ce decouplage garantit qu'aucune dependance ne va du bundle vers l'application.
Interfaces internes remplacables
Ces ports possedent une implementation par defaut fournie par le bundle, et sont substituables par l'application via decoration/alias DI.
| Interface | Implementation par defaut | Role |
|---|---|---|
| Service de chat | orchestrateur d'un tour de chat | orchestration RAG |
| Client de chat | client LLM (API Messages) | port LLM du chat |
| Summarizer (auto-tag) | summarizer LLM | resume d'article |
| Classifier (auto-tag) | classifier par mots-cles | theme + score |
| Collector (auto-tag) | collecteur RSS/Atom | collecte d'une source |
| Fetcher d'article | extracteur de texte | extraction du contenu |
| Writer de proposition | ecriture Markdown | ecriture de la proposition |
| Lanceur de re-indexation | lanceur detache | re-indexation en tache de fond |
| Lanceur de checkout corpus | lanceur detache | checkout git en tache de fond |
| Client Admin API | client usage/cout | metriques org-wide |
Un registre de collecteurs retourne le premier collecteur dont supports() couvre le type de la source, sinon leve une exception. Ajouter un type de source = implementer l'interface auto-taggee, qui est decouverte automatiquement.
Signatures utiles a l'integrateur
- Poser une question au chat :
ask(string $question, array $history, ChatSettings $settings): ChatAnswer, ou$historyest une liste chronologique{role, content}bornee par l'appelant. - Fabrique de reglages de chat : defauts / profil assistant (avec surcharges) / profil chat embarque.
- Resume :
summarize(string $title, string $url, string $content): SummaryResult. - Client Admin API :
isConfigured(), usage par modele, cout par modele, usage detaille, liste des cles.
Exceptions publiques
Exceptions dediees portant un contexte de diagnostic : chat (avec statut HTTP), summarizer (avec requete envoyee, reponse brute, statut HTTP), collecteur, et erreurs Admin API.
Modele de donnees (entites auto-mappees)
Les entites Doctrine sont mappees par attributs. Le bundle ne fournit pas de migrations : l'application hote genere et applique le schema.
Domaine Veille
- Source de veille :
slug(unique, minuscules/tirets),name,url,type(rss | atom | html), cadence (chaine de type duree ISO 8601, informative), theme par defaut, interrupteurisActive, pause automatiquestandby(avec horodatage et raison), compteur d'echecs consecutifs, description editoriale, horodatages. L'entite porte sa logique de succes/echec/mise en veille. - Item de veille : rattache a une source (cascade),
urlindexee, hash de contenu, titre (+ titre FR), dates de collecte/traitement, theme,status(pending → proposed | failed, puis accepted | rejected), contenu brut, resume, score de pertinence, modele utilise, chemin de proposition, message d'erreur. Relation un-a-plusieurs vers les tentatives. - Tentative de traitement : journal de diagnostic d'une passe (etape atteinte fetch/classify/summarize/write/done, issue, duree), detail du fetch (statut HTTP, octets, caracteres extraits, erreur), detail de l'appel LLM (modele, requete, reponse brute tronquee, statut HTTP, tokens in/out), classe et message d'erreur.
- Lecture : « cet utilisateur a lu ce billet » ; unicite (utilisateur, item), absence de ligne = non lu. L'utilisateur est reference via l'interface resolue cote application.
Domaine Chat
- Configuration de chat (singleton) : modele (liste blanche), nombre de passages (1..20), seuil de score (0..1), temperature (0..1), max tokens (256..4096), tours d'historique (0..20). Une seule ligne attendue.
Domaine Metrics
- Snapshot quotidien : agrege par (jour, label) ; tokens (input non cache, lecture cache, creation cache, output), requetes web search, cout en cents (decimal). Upsert idempotent par (jour, label).
- Usage dimensionnel : par (jour, modele, cle API, service tier), tokens seulement. Upsert par le quadruplet.
- Cache de cle API : id → nom, pour afficher des noms lisibles.
- Alerte de cout : seuil en devise, periode (daily | monthly), e-mail destinataire, activable, anti-spam par periode notifiee.
Chaque entite dispose d'un repository dedie exposant des requetes de listing, de curation et d'agregation : c'est le point d'entree « lecture » de l'UI de l'application hote.
Comportements de contrat notables
- Cycle de veille : declenche par un message (scheduler ou manuel). Ingestion (collecte + deduplication par URL/hash + persistance en pending) puis traitement FIFO par lot : fetch conditionnel si le contenu est insuffisant, garde-fou anti-contenu-vide (item marque failed plutot que resumer un titre seul), classification, resume, ecriture de la proposition. Chaque item est idempotent et isole ; un echec ne casse pas le lot.
- Mise en veille automatique (standby) : distincte de l'interrupteur humain ; apres un seuil configurable d'echecs consecutifs, la source est mise en pause ; un succes remet le compteur a zero ; un humain peut lever la pause.
- Garde-fou RAG du chat : si aucun passage ou si le meilleur score est sous le seuil, le composant renvoie « information absente de la documentation » sans appeler le LLM (anti-hallucination + economie). Sinon, prompt assemble (system + passages numerotes + historique + question) et reponse sourcee (texte Markdown, liste de sources avec chemin/titre/section/ancre/score, modele, tokens, meilleur score, latence).
- Bornage des reglages de chat : toute valeur est clampee (min/max + liste blanche de modeles) a l'assemblage ; ni session ni configuration aberrante ne peuvent casser l'appel ou faire deriver le cout.
- Rendu sur : le rendu Markdown → HTML est escape-first et ne conserve qu'un sous-ensemble (gras, listes, liens http/https) ; aucun HTML brut de la source ne survit.
- Bibliotheque de docs : acces en lecture au corpus en mode default-allow (tous les
.mdlisibles sauf exclusions permanentes et dotfiles), avec double garde-fou anti path-traversal (policy + confinement physique borne a la racine du corpus). - Taches de fond : re-indexation et checkout sont lances en process detaches (fire-and-forget) ; le suivi passe par des reglages cle/valeur (verrou
running+ horodatage), relaches enfinally. - Synchronisation metriques : idempotente ; no-op silencieux sans cle Admin ; les alertes de cout sont evaluees sur les donnees fraiches apres chaque synchro (une notification par franchissement et par periode).
Points de contrat pour l'integrateur
Cote application hote, les responsabilites sont :
- Installer le bundle et ses dependances (bundle RAG + bundle utilitaire), puis l'enregistrer.
- Resoudre l'entite utilisateur vers l'interface de lecteur de veille (contrat obligatoire, sinon le mapping echoue).
- Inclure les entites du bundle dans le mapping Doctrine et generer/appliquer le schema (aucune migration fournie).
- Definir les variables d'environnement attendues (cles LLM et Admin API, modeles et plafonds tokens, cadence et taille de lot veille, seuils de reglages chat, parametres de checkout corpus). En leur absence, des defauts codes s'appliquent (et la synchro metriques est no-op sans cle Admin).
- Fournir l'UI, le template e-mail d'alerte et les repertoires de travail (clone du corpus, dossier des propositions) sous le repertoire projet.
- Faire tourner le pipeline via le consommateur du scheduler, ou manuellement via les commandes console (ingestion, traitement, backfill titre FR, synchro metriques, re-indexation, checkout).
Services publics principaux a injecter : service de chat, fabrique de reglages, services d'ingestion et de traitement veille, importeur de sources (CSV upsert par slug), rendu HTML sur, bibliotheque et gestionnaire de corpus, lanceurs de tache de fond, service de synchro et service d'analytics metriques, et les repositories de lecture.