<?xml
version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom"
>

<channel xml:lang="fr">
	<title>Les services IA de DnC</title>
	<link>https://ia.dnc.global/</link>
	<description>En mati&#232;re d'intelligence artificielle (IA), DnC met l'accent sur la s&#233;curit&#233; en offrant aux entreprises le moyen de conserver leurs donn&#233;es et les traitements &#224; l'int&#233;rieur de leur r&#233;seau d'entreprise plut&#244;t que dans le Cloud.</description>
	<language>fr</language>
	<generator>SPIP - www.spip.net</generator>
	<atom:link href="https://ia.dnc.global/spip.php?id_rubrique=7&amp;page=backend" rel="self" type="application/rss+xml" />




<item xml:lang="fr">
		<title>Le Daemon Pyro5</title>
		<link>https://ia.dnc.global/Le-Daemon-Pyro5.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Le-Daemon-Pyro5.html</guid>
		<dc:date>2026-07-07T09:30:51Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Dans une architecture multi&#8209;processus et multi&#8209;utilisateur, on ne peut charger un m&#234;me mod&#232;le dans chaque composant (NSOrchestrator, ReActEngine, workers, tests, scripts). Pour cette raison, les mod&#232;les doivent &#234;tre servis via un daemon. &lt;br class='autobr' /&gt;
##Position du probl&#232;me &lt;br class='autobr' /&gt;
Un LLM ou un SLM repr&#233;sente plusieurs gigaoctets en m&#233;moire, et leur rechargement dans chaque processus provoquerait une explosion de la consommation RAM, une fragmentation CUDA, des temps de d&#233;marrage prohibitifs et une instabilit&#233; g&#233;n&#233;rale (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-v200-.html" rel="directory"&gt;Architecture v200&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Dans une architecture multi&#8209;processus et multi&#8209;utilisateur, on ne peut charger un m&#234;me mod&#232;le dans chaque composant (NSOrchestrator, ReActEngine, workers, tests, scripts).&lt;br class='autobr' /&gt;
Pour cette raison, les mod&#232;les doivent &#234;tre servis via un daemon.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;h2&gt;Position du probl&#232;me&lt;/h2&gt;
&lt;p&gt;Un LLM ou un SLM repr&#233;sente plusieurs gigaoctets en m&#233;moire, et leur rechargement dans chaque processus provoquerait une explosion de la consommation RAM, une fragmentation CUDA, des temps de d&#233;marrage prohibitifs et une instabilit&#233; g&#233;n&#233;rale du syst&#232;me. Le &lt;strong&gt;mode daemon&lt;/strong&gt; r&#233;sout ce probl&#232;me en garantissant qu'&lt;strong&gt;un mod&#232;le n'est charg&#233; qu'une seule fois dans un processus d&#233;di&#233;, puis partag&#233; entre tous les autres via RPC&lt;/strong&gt;. Cela permet un fonctionnement r&#233;ellement concurrent, une gestion propre du streaming token&#8209;par&#8209;token, une isolation des erreurs, et une stabilit&#233; m&#233;moire indispensable en production.&lt;/p&gt;
&lt;p&gt;Pour cette raison, le LLM et le SLM doivent &#234;tre servis via un daemon. Les deux mod&#232;les sont sollicit&#233;s par plusieurs utilisateurs, plusieurs sessions et plusieurs moteurs internes, parfois simultan&#233;ment. Les Thought et les r&#233;ponses finales de ReAct doivent &#234;tre g&#233;n&#233;r&#233;es sans jamais recharger les poids des mod&#232;les, sans bloquer les autres processus, et sans d&#233;pendre de l'environnement local de chaque composant. En les ex&#233;cutant tous deux en daemon, l'architecture v200 devient coh&#233;rente, d&#233;terministe et scalable : un seul chargement, un seul point d'acc&#232;s, un comportement identique pour tous les clients, et une capacit&#233; &#224; monter en charge sans modifier le code des orchestrateurs ou des moteurs internes.&lt;/p&gt;
&lt;p&gt;Ce raisonnement vaut &#233;galement pour les index.&lt;/p&gt;
&lt;h2&gt;R&#244;le du daemon&lt;/h2&gt;
&lt;p&gt;Le daemon Pyro5 est un fournisseur multi-services.&lt;/p&gt;
&lt;p&gt;Via ModelsConfigurator, il :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Charge les mod&#232;les d&#233;finis dans &lt;code&gt;models.json&lt;/code&gt;,
ce qui initialise AppSettings et les mod&#232;les globaux (embedding, LLM, SLM).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Charge les services d&#233;clar&#233;s dans &lt;code&gt;services.json&lt;/code&gt; et les instancie dynamiquement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enregistre chaque service dans Pyro5 sous un nom stable :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;llm.server&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;slm.server&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;embedding.server&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;rag.reader&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Puis : Lance la boucle d'&#233;v&#233;nements Pyro5.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemple : chargement d'un index par RagRuntime :&lt;/strong&gt;&lt;/p&gt;
&lt;dl class='spip_document_56 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/in_daemon_rag_reader_workflow-2026-07-07-091503.png' class=&#034;mediabox&#034; title=&#034;PNG - 737.1 ko&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH320/in_daemon_rag_reader_workflow-2026-07-07-091503-2f088.png?1783416584' width='500' height='320' alt=&#034;PNG - 737.1&#160;ko&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;h2&gt;Composants principaux&lt;/h2&gt;
&lt;h3&gt;1. MemoryManager&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Arbitre global de la RAM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Suit les allocations d'objets persistants.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Applique une politique d'&#233;viction (LRU locale).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournit un &#233;tat m&#233;moire complet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thread-safe.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. InDaemonRagReader&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Reader interne au daemon.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Encode les requ&#234;tes via le mod&#232;le d'embedding global.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Interroge le backend vectoriel (FAISS, LlamaIndex ...).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Renvoie des &lt;code&gt;RichNode&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fournit un mode streaming (&lt;code&gt;astream&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Noter qu'une architecture s&#233;parant le mod&#232;le d'embedding et l'index dans des daemons distincts conduirait &#224; un grand nombre d'&#233;changes RCP et &#224; des temps de traitement prohibitifs.&lt;/p&gt;
&lt;h2&gt;Interaction avec le client&lt;/h2&gt;
&lt;p&gt;Le client utilise &lt;strong&gt;InDaemonRagReaderProxy&lt;/strong&gt; pour contacter &lt;code&gt;rag.reader&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Flux typique :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RagRuntime.retrieve() &#8594; InDaemonRagReaderProxy(&#034;rag.reader&#034;).retrieve(theme, query, top_k) &#8594; InDaemonRagReader.retrieve() &#8594; encode la requ&#234;te &#8594; interroge le backend vectoriel &#8594; renvoie des RichNode&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Le client ne voit jamais MemoryManager : tout est encapsul&#233; dans le daemon.&lt;/p&gt;
&lt;h2&gt;Avantages de cette architecture&lt;/h2&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Un seul daemon &#8594; coh&#233;rence m&#233;moire.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Plusieurs services &#8594; modularit&#233;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MemoryManager central &#8594; contr&#244;le RAM industriel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;InDaemonRagReader &#8594; moteur RAG unifi&#233;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Structure simple &#8594; facile &#224; &#233;tendre.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>v200 : Introduction</title>
		<link>https://ia.dnc.global/v200-Introduction.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/v200-Introduction.html</guid>
		<dc:date>2026-07-04T08:16:29Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;La v200 introduit une architecture RAG enti&#232;rement refondue, centr&#233;e sur la modularit&#233;, la performance et la robustesse. Elle s'appuie sur l'&#233;criture de services d&#233;di&#233;s pour les mod&#232;les et les index, un daemon Pyro5 pour l'acc&#232;s rapide aux index en m&#233;moire, et une API interne unifi&#233;e permettant d'abstraire totalement les backends. L'ensemble garantit un moteur RAG totalement ind&#233;pendant de toute biblioth&#232;que (LlamaIndex, LangChain ...) . Cette version fournit ainsi une base industrielle, stable et (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-v200-.html" rel="directory"&gt;Architecture v200&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;La v200 introduit une architecture RAG enti&#232;rement refondue, centr&#233;e sur la modularit&#233;, la performance et la robustesse. Elle s'appuie sur l'&#233;criture de services d&#233;di&#233;s pour les mod&#232;les et les index, un daemon Pyro5 pour l'acc&#232;s rapide aux index en m&#233;moire, et une API interne unifi&#233;e permettant d'abstraire totalement les backends. &lt;br class='autobr' /&gt;
L'ensemble garantit un moteur RAG totalement ind&#233;pendant de toute biblioth&#232;que (LlamaIndex, LangChain ...) . &lt;br class='autobr' /&gt;
Cette version fournit ainsi une base industrielle, stable et extensible pour un pipeline RAG totalement propri&#233;taire.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;p&gt;La &lt;strong&gt;v200&lt;/strong&gt; constitue une r&#233;architecture compl&#232;te du pipeline RAG, con&#231;ue pour offrir une modularit&#233; stricte, une ind&#233;pendance vis&#8209;&#224;&#8209;vis de LlamaIndex ou de toute autre biblioth&#232;que, et une performance accrue gr&#226;ce &#224; un daemon g&#233;rant les index en m&#233;moire persistante. Elle introduit une s&#233;paration nette des responsabilit&#233;s, une normalisation des API internes, et un mod&#232;le d'ex&#233;cution coh&#233;rent pour tous les types d'index et de mod&#232;les.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;1. Objectif : Modularit&#233; syst&#233;mique&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;1.1. Modularit&#233; des mod&#232;les&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;La v200 d&#233;finit des services d&#233;di&#233;s pour les mod&#232;les :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;services/llm/&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;services/embeddings/&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chaque service expose une API normalis&#233;e :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;generate()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;astream()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;embed()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cette abstraction permet de remplacer un mod&#232;le (OpenAI, Ollama, HF, local) sans impact sur le reste du pipeline.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1.2. Modularit&#233; des index&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Les index sont encapsul&#233;s dans des backends interchangeables :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;FaissBackend&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;LlamaIndexBackend&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DummyBackend&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tous impl&#233;mentent une &lt;strong&gt;API unifi&#233;e&lt;/strong&gt; :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;retrieve(query, top_k)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;query(query)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;astream(query)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ping()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cette normalisation garantit que le RAG ne d&#233;pend plus du type d'index sous&#8209;jacent.&lt;/p&gt;
&lt;dl class='spip_document_51 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/ragruntime_retrieve-2026-07-04-105144.png' class=&#034;mediabox&#034; title=&#034;PNG - 2.1 Mo&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH320/ragruntime_retrieve-2026-07-04-105144-63cf4.png?1783163163' width='500' height='320' alt=&#034;PNG - 2.1&#160;Mo&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;h3&gt;&lt;strong&gt;1.3. Rapidit&#233; via daemon Pyro5&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;La v200 introduit un daemon Pyro5 :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;charg&#233; de maintenir les index en m&#233;moire,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;exposant une API RPC homog&#232;ne,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;permettant un acc&#232;s rapide depuis n'importe quel worker.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le client est minimal :&lt;/p&gt;
&lt;p&gt;IndexesManager &#8594; IndexService &#8594; RemoteIndexBackend&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Un m&#233;canisme de **fallback local** assure la continuit&#233; de service en cas d'indisponibilit&#233; du daemon. &lt;p&gt;### **1.4. Couche interne de normalisation**
Une couche interne (`internal/`) garantit :&lt;/p&gt;
&lt;p&gt;- la normalisation des r&#233;sultats des backends,
- la conversion des formats h&#233;t&#233;rog&#232;nes en structures standardis&#233;es,
- la coh&#233;rence des donn&#233;es consomm&#233;es par RagRuntime.&lt;/p&gt;
&lt;p&gt;Tous les r&#233;sultats sont convertis en dictionnaires homog&#232;nes :&lt;/p&gt;
&lt;p&gt;```python
{ &#034;text&#034;: &#034;...&#034;, &#034;score&#034;: None, &#034;metadata&#034;: {}
}&lt;/code&gt;&lt;/p&gt;
&lt;/pre&gt;
&lt;h2&gt;&lt;strong&gt;2. Objectif : RAGEngine ind&#233;pendant d'API externes&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;2.1. Suppression des d&#233;pendances structurelles&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;La v200 &#233;limine toute d&#233;pendance directe &#224; LlamaIndex ( ou autre) dans le moteur RAG :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;plus de &lt;code&gt;QueryEngine&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;plus de &lt;code&gt;Node&lt;/code&gt;, &lt;code&gt;Document&lt;/code&gt;, &lt;code&gt;Response&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;plus de formats &#233;trangers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Par exemple, LlamaIndex est encapsul&#233; dans &lt;code&gt;LlamaIndexBackend&lt;/code&gt;, qui expose l'API unifi&#233;e.
Dans l'&#233;tat actuel du d&#233;veloppement, il existe une adaptation &#224; FAISS.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;2.2. RAGEngine bas&#233; sur une API interne stable&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Le moteur RAG (RagRuntime) ne d&#233;pend plus :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;du type d'index,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;du type de mod&#232;le,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;de LlamaIndex ou FAISS.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il consomme uniquement l'API unifi&#233;e :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;retrieve()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;query()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;astream()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;2.3. Normalisation syst&#233;matique des r&#233;sultats&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Les r&#233;sultats bruts des backends (souvent des cha&#238;nes de caract&#232;res) sont syst&#233;matiquement convertis en objets structur&#233;s avant traitement par RagRuntime.&lt;/p&gt;
&lt;p&gt;Cela garantit :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;la stabilit&#233; du pipeline,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;la compatibilit&#233; avec les hooks,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;l'absence d'erreurs li&#233;es &#224; des formats h&#233;t&#233;rog&#232;nes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;2.4. Fallback local coh&#233;rent&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;En cas d'indisponibilit&#233; du daemon :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;IndexService.connect() &#8594; RemoteIndexBackend (si daemon disponible) &#8594; LocalIndexBackend (si daemon indisponible)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;LocalIndexBackend&lt;/code&gt; est un proxy thread&#8209;safe, totalement ind&#233;pendant du type d'index.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Synth&#232;se&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;La &lt;strong&gt;v200&lt;/strong&gt; est une architecture RAG :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;modulaire&lt;/strong&gt;, gr&#226;ce &#224; des services d&#233;di&#233;s pour les mod&#232;les et les index,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;performante&lt;/strong&gt;, via un daemon Pyro5 servant les index en m&#233;moire,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;normalis&#233;e&lt;/strong&gt;, gr&#226;ce &#224; une API interne unifi&#233;e pour tous les backends,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;r&#233;siliente&lt;/strong&gt;, via un fallback local automatique,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ind&#233;pendante de LlamaIndex&lt;/strong&gt;, gr&#226;ce &#224; l'encapsulation compl&#232;te dans &lt;code&gt;LlamaIndexBackend&lt;/code&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;stable&lt;/strong&gt;, gr&#226;ce &#224; une couche de normalisation syst&#233;matique pour RagRuntime.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Elle constitue une base industrielle, coh&#233;rente, et extensible pour un pipeline RAG moderne.&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Politique LRU/MRU</title>
		<link>https://ia.dnc.global/Politique-LRU-MRU.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Politique-LRU-MRU.html</guid>
		<dc:date>2026-06-29T09:04:20Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Dans l'architecture Pyro5, les index ( et certains mod&#232;les ) sont charg&#233;s depuis le disque puis conserv&#233;s en RAM pour &#234;tre accessibles rapidement par les services distants. Le daemon joue le r&#244;le de processus ma&#238;tre. &lt;br class='autobr' /&gt;
Pour les index par exemple, il les expose via IndexServer, et sert de point d'acc&#232;s unique pour tous les RemoteIndexService. Comme ces index peuvent &#234;tre volumineux et que le daemon est con&#231;u pour rester actif longtemps, il doit g&#233;rer sa m&#233;moire de mani&#232;re autonome et efficace. C'est (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-v200-.html" rel="directory"&gt;Architecture v200&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Dans l'architecture Pyro5, les index ( et certains mod&#232;les ) sont charg&#233;s depuis le disque puis conserv&#233;s en RAM pour &#234;tre accessibles rapidement par les services distants. Le daemon joue le r&#244;le de processus ma&#238;tre.&lt;/p&gt;
&lt;p&gt;Pour les index par exemple, il les expose via IndexServer, et sert de point d'acc&#232;s unique pour tous les RemoteIndexService.&lt;/p&gt;
&lt;p&gt;Comme ces index peuvent &#234;tre volumineux et que le daemon est con&#231;u pour rester actif longtemps, il doit g&#233;rer sa m&#233;moire de mani&#232;re autonome et efficace. C'est pr&#233;cis&#233;ment pour cela qu'une politique LRU/MRU est indispensable : elle permet de conserver en RAM les index les plus r&#233;cemment utilis&#233;s (MRU), tout en &#233;vin&#231;ant automatiquement ceux qui ne sont plus sollicit&#233;s (LRU).&lt;/p&gt;
&lt;p&gt;Cette strat&#233;gie garantit que le flowchart Pyro5 fonctionne de mani&#232;re fluide, sans surcharge m&#233;moire, et que les services distants acc&#232;dent toujours aux index pertinents sans rechargement inutile depuis le disque.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;h1&gt;Politique LRU/MRU&lt;/h1&gt;
&lt;p&gt;La politique &lt;strong&gt;LRU/MRU&lt;/strong&gt; (Least Recently Used / Most Recently Used) est un m&#233;canisme de gestion de la m&#233;moire qui permet de d&#233;cider &lt;strong&gt;quel objet doit &#234;tre &#233;vinc&#233;&lt;/strong&gt; lorsque la RAM atteint sa capacit&#233; maximale. Elle repose sur un principe simple : &lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;MRU&lt;/strong&gt; = objets r&#233;cemment utilis&#233;s &#8594; &#224; conserver &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LRU&lt;/strong&gt; = objets peu utilis&#233;s r&#233;cemment &#8594; candidats &#224; l'&#233;viction &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans notre syst&#232;me, cette politique est appliqu&#233;e par le &lt;strong&gt;MemoryManager&lt;/strong&gt;, qui maintient un ordre strict des objets en RAM gr&#226;ce &#224; un &lt;code&gt;OrderedDict&lt;/code&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;MRU &#8212; Most Recently Used&lt;/h2&gt;
&lt;p&gt;Un objet devient &lt;strong&gt;MRU&lt;/strong&gt; lorsqu'il est :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;charg&#233; en RAM,&lt;/li&gt;
&lt;li&gt;acc&#233;d&#233; via &lt;code&gt;get()&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;marqu&#233; via &lt;code&gt;touch()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le MemoryManager d&#233;place alors la cl&#233; &lt;strong&gt;&#224; la fin&lt;/strong&gt; de l'OrderedDict :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ LRU ... &#8594; ... MRU ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cela signifie :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;cet index est actif,&lt;/li&gt;
&lt;li&gt;il doit &#234;tre conserv&#233; en priorit&#233;,&lt;/li&gt;
&lt;li&gt;il ne doit pas &#234;tre &#233;vinc&#233; tant que d'autres objets moins utilis&#233;s existent.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;LRU &#8212; Least Recently Used&lt;/h2&gt;
&lt;p&gt;L'objet &lt;strong&gt;LRU&lt;/strong&gt; est celui qui :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;n'a pas &#233;t&#233; utilis&#233; depuis le plus longtemps,&lt;/li&gt;
&lt;li&gt;n'a pas &#233;t&#233; touch&#233; r&#233;cemment,&lt;/li&gt;
&lt;li&gt;se trouve &lt;strong&gt;au d&#233;but&lt;/strong&gt; de l'OrderedDict.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lorsqu'une &#233;viction est n&#233;cessaire (ex : &lt;code&gt;len(store) &gt; max_items&lt;/code&gt;), le MemoryManager fait :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;key, _ = self._store.popitem(last=False)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce qui retire &lt;strong&gt;le premier &#233;l&#233;ment&lt;/strong&gt;, donc le LRU.&lt;/p&gt;
&lt;h2&gt;Pourquoi LRU/MRU est id&#233;al dans ton architecture&lt;/h2&gt;
&lt;h3&gt;1. &lt;strong&gt;Les index sont lourds&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Ils peuvent peser plusieurs centaines de Mo.&lt;br /&gt;
Il est donc crucial d'&#233;viter de recharger inutilement depuis le disque.&lt;/p&gt;
&lt;h3&gt;2. &lt;strong&gt;Les RemoteIndexService sont stateless&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Ils ne conservent rien : tout repose sur la RAM du daemon.&lt;br /&gt;
LRU/MRU garantit que les index r&#233;ellement utilis&#233;s restent disponibles.&lt;/p&gt;
&lt;h3&gt;3. &lt;strong&gt;Le daemon est long-lived&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Il doit s'auto-r&#233;guler sans intervention humaine.&lt;br /&gt;
LRU/MRU fournit une politique simple, d&#233;terministe et efficace.&lt;/p&gt;
&lt;h3&gt;4. &lt;strong&gt;Les th&#232;mes ont des patterns d'acc&#232;s naturels&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Certains th&#232;mes sont consult&#233;s souvent (MRU), d'autres rarement (LRU).&lt;br /&gt;
La politique s'adapte automatiquement &#224; ces usages.&lt;/p&gt;
&lt;h2&gt;R&#233;sultat : une m&#233;moire auto-optimis&#233;e&lt;/h2&gt;
&lt;p&gt;Gr&#226;ce &#224; LRU/MRU :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Les index actifs restent en RAM &#8594; &lt;strong&gt;latence minimale&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Les index inactifs sont &#233;vinc&#233;s &#8594; &lt;strong&gt;RAM ma&#238;tris&#233;e&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Le daemon ne recharge que si n&#233;cessaire &#8594; &lt;strong&gt;I/O minimis&#233;es&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Le syst&#232;me reste stable m&#234;me sous forte charge &#8594; &lt;strong&gt;robustesse&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Construction des mod&#232;les : models.json et services.json</title>
		<link>https://ia.dnc.global/Construction-des-modeles-models-json-et-services-json.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Construction-des-modeles-models-json-et-services-json.html</guid>
		<dc:date>2026-06-23T08:51:00Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;L'architecture v200 repose sur une s&#233;paration stricte entre la d&#233;finition des mod&#232;les, leur construction centralis&#233;e, et la d&#233;claration des services qui les consomment. &lt;br class='autobr' /&gt;
Les mod&#232;les sont d&#233;crits dans un fichier unique (`models.json`), puis construits une seule fois au d&#233;marrage par le `ModelsConfigurator`, avant d'&#234;tre stock&#233;s dans `AppSettings` pour &#234;tre partag&#233;s par l'ensemble du runtime. &lt;br class='autobr' /&gt;
Les services Pyro5, d&#233;clar&#233;s dans `services.json`, ne chargent jamais de mod&#232;les eux&#8209;m&#234;mes : ils se contentent (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-v200-.html" rel="directory"&gt;Architecture v200&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;L'architecture v200 repose sur une s&#233;paration stricte entre la d&#233;finition des mod&#232;les, leur &lt;a href='https://ia.dnc.global/Trois-modes-de-chargement-des-modeles.html' class='spip_in'&gt;construction centralis&#233;e&lt;/a&gt;, et la d&#233;claration des services qui les consomment. &lt;br class='autobr' /&gt;
Les mod&#232;les sont d&#233;crits dans un fichier unique (`models.json`), puis construits une seule fois au d&#233;marrage par le `ModelsConfigurator`, avant d'&#234;tre stock&#233;s dans `AppSettings` pour &#234;tre partag&#233;s par l'ensemble du runtime. &lt;br class='autobr' /&gt;
Les services Pyro5, d&#233;clar&#233;s dans `services.json`, ne chargent jamais de mod&#232;les eux&#8209;m&#234;mes : ils se contentent d'exposer des capacit&#233;s en s'appuyant sur les objets d&#233;j&#224; initialis&#233;s, garantissant ainsi coh&#233;rence, performance et isolation des responsabilit&#233;s.&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div &lt;div class='rss_ps'&gt;&lt;hr /&gt;
&lt;h1&gt;Construction des mod&#232;les : &lt;code&gt;models.json&lt;/code&gt; et &lt;code&gt;services.json&lt;/code&gt;&lt;/h1&gt;
&lt;h2&gt;1. Pr&#233;sentation g&#233;n&#233;rale : comment les mod&#232;les sont construits dans v200&lt;/h2&gt;
&lt;p&gt;L'architecture v200 repose sur une s&#233;paration stricte des responsabilit&#233;s :&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1. &lt;code&gt;models.json&lt;/code&gt; d&#233;crit les mod&#232;les&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Ce fichier d&#233;clare &lt;em&gt;uniquement&lt;/em&gt; les mod&#232;les utilis&#233;s par le runtime :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;embedding &lt;/li&gt;
&lt;li&gt;slm &lt;/li&gt;
&lt;li&gt;tokenizer &lt;/li&gt;
&lt;li&gt;llm &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chaque entr&#233;e d&#233;crit :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;model_name&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;model_path&lt;/code&gt; (optionnel) &lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;device&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;api_key_env&lt;/code&gt; (si backend = API)
etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;2. ModelsConfigurator construit les mod&#232;les&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Le composant &lt;code&gt;ModelsConfigurator&lt;/code&gt; :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;lit &lt;code&gt;models.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;instancie les mod&#232;les (HF, API, local, etc.)&lt;/li&gt;
&lt;li&gt;cr&#233;e les objets Python correspondants&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il ne conna&#238;t pas les services Pyro5.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;3. AppSettingsManager stocke les mod&#232;les&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Une fois construits, les mod&#232;les sont transmis &#224; :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;AppSettingsManager.load_models(...)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce composant :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;cr&#233;e un objet &lt;code&gt;AppSettings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;stocke les mod&#232;les dans des attributs statiques&lt;/li&gt;
&lt;li&gt;verrouille la configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;4. Les services Pyro5 consomment les mod&#232;les&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Les services (EmbeddingServer, SLMServer, IndexServer, MemoryManager) :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;ne chargent pas de mod&#232;les&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ne re&#231;oivent pas de param&#232;tres de mod&#232;le&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;r&#233;cup&#232;rent les mod&#232;les via :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;from runtime_v2.settings.app_settings import AppSettings self.embedding = AppSettings.embedding
self.slm = AppSettings.slm
self.tokenizer = AppSettings.tokenizer
self.llm = AppSettings.llm&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;5. &lt;code&gt;services.json&lt;/code&gt; d&#233;crit uniquement les services&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Ce fichier :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;d&#233;clare les services Pyro5&lt;/li&gt;
&lt;li&gt;indique leur classe Python&lt;/li&gt;
&lt;li&gt;fournit uniquement les param&#232;tres n&#233;cessaires aux RPC (ex : nom d'un autre service)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il &lt;strong&gt;ne doit jamais contenir de param&#232;tres de mod&#232;le&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Comment &#233;crire &lt;code&gt;models.json&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Voici la structure de base :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#034;__comment&#034;: &#034;Source de ModelsConfigurator pour la configuration des mod&#232;les du runtime v200.&#034;, &#034;embedding&#034;: { &#034;__comment&#034;: &#034;Embedding local bas&#233; sur SentenceTransformers (ST). Utilise BGE-small en mode l&#233;ger, sans AutoModel/AutoTokenizer, pour &#233;viter la surcharge m&#233;moire des mod&#232;les HF.&#034;, &#034;model_type&#034;: &#034;embedding&#034;, &#034;model_name&#034;: &#034;BAAI/bge-small-en-v1.5&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/bge-small&#034;, &#034;backend&#034;: &#034;st&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;slm&#034;: { &#034;__comment&#034;: &#034;SLM local optionnel (TinyLlama, Phi, etc.). Null = d&#233;sactiv&#233;.&#034;, &#034;model_type&#034;: &#034;causal_lm&#034;, &#034;model_name&#034;: null, &#034;model_path&#034;: null, &#034;backend&#034;: null, &#034;device&#034;: null }, &#034;tokenizer&#034;: { &#034;__comment&#034;: &#034;Tokenizer HF externe (Mixtral), t&#233;l&#233;charg&#233; via HF.&#034;, &#034;model_type&#034;: &#034;tokenizer&#034;, &#034;model_name&#034;: &#034;mistralai/Mixtral-8x7B-Instruct-v0.1&#034;, &#034;model_path&#034;: null, &#034;backend&#034;: &#034;hf&#034;, &#034;device&#034;: null }, &#034;llm&#034;: { &#034;__comment&#034;: &#034;LLM principal via Daemon.&#034;, &#034;model_type&#034;: &#034;causal_lm&#034;, &#034;backend&#034;: &#034;mistral_daemon&#034;, &#034;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;api_key_env&#034;: &#034;MISTRAL_API_KEY&#034;, &#034;daemon_host&#034;: &#034;127.0.0.1&#034;, &#034;daemon_port&#034;: 50050 }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ou, plus ambitieux ( &#224; condition que les backends aient &#233;t&#233; &#233;crits) :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#034;__comment&#034;: &#034;Configuration canonique v200 &#8212; aucun champ implicite, aucun type d&#233;duit automatiquement.&#034;, &#034;llm_api&#034;: { &#034;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;backend&#034;: &#034;mistral_api&#034;, &#034;model_type&#034;: &#034;causal_lm&#034;, &#034;api_key_env&#034;: &#034;MISTRAL_API_KEY&#034;, &#034;max_new_tokens&#034;: 2048, &#034;temperature&#034;: 0.2 }, &#034;llm_daemon&#034;: { &#034;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;backend&#034;: &#034;mistral_daemon&#034;, &#034;model_type&#034;: &#034;causal_lm&#034;, &#034;api_key&#034;: &#034;env:MISTRAL_API_KEY&#034;, &#034;daemon_host&#034;: &#034;127.0.0.1&#034;, &#034;daemon_port&#034;: 50050, &#034;max_new_tokens&#034;: 2048, &#034;temperature&#034;: 0.0 }, &#034;slm&#034;: { &#034;model_name&#034;: &#034;TinyLlama/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;backend&#034;: &#034;hf_local&#034;, &#034;model_type&#034;: &#034;hf_causal_lm&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;device&#034;: &#034;cpu&#034;, &#034;dtype&#034;: &#034;float16&#034;, &#034;max_new_tokens&#034;: 512, &#034;temperature&#034;: 0.0 }, &#034;embedding&#034;: { &#034;model_name&#034;: &#034;BAAI/bge-small-en-v1.5&#034;, &#034;backend&#034;: &#034;st&#034;, &#034;model_type&#034;: &#034;embedding&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/bge-small&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;tokenizer&#034;: { &#034;model_name&#034;: &#034;mistralai/Mixtral-8x7B-Instruct-v0.1&#034;, &#034;backend&#034;: &#034;hf&#034;, &#034;model_type&#034;: &#034;tokenizer&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;service_router&#034;: { &#034;model_name&#034;: &#034;router-v1&#034;, &#034;backend&#034;: &#034;internal&#034;, &#034;model_type&#034;: &#034;router&#034;, &#034;strategy&#034;: &#034;round_robin&#034;, &#034;targets&#034;: [&#034;llm_api&#034;, &#034;llm_daemon&#034;, &#034;slm&#034;] }, &#034;reranker&#034;: { &#034;model_name&#034;: &#034;colbertv2&#034;, &#034;backend&#034;: &#034;hf_local&#034;, &#034;model_type&#034;: &#034;reranker&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/colbertv2&#034;, &#034;device&#034;: &#034;cuda&#034;, &#034;dtype&#034;: &#034;float16&#034; }, &#034;vision_encoder&#034;: { &#034;model_name&#034;: &#034;openai/clip-vit-base-patch32&#034;, &#034;backend&#034;: &#034;hf_local&#034;, &#034;model_type&#034;: &#034;vision_encoder&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/clip-vit-base-patch32&#034;, &#034;device&#034;: &#034;cuda&#034; }, &#034;audio_encoder&#034;: { &#034;model_name&#034;: &#034;facebook/wav2vec2-base-960h&#034;, &#034;backend&#034;: &#034;hf_local&#034;, &#034;model_type&#034;: &#034;audio_encoder&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/wav2vec2&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;http_service&#034;: { &#034;model_name&#034;: &#034;custom-service&#034;, &#034;backend&#034;: &#034;http&#034;, &#034;model_type&#034;: &#034;service&#034;, &#034;service_url&#034;: &#034;http://127.0.0.1:8080/infer&#034;, &#034;timeout&#034;: 30 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;R&#232;gles :&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;Chaque mod&#232;le doit avoir un &lt;code&gt;model_name&lt;/code&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;model_path&lt;/code&gt; peut &#234;tre &lt;code&gt;null&lt;/code&gt; si HF doit t&#233;l&#233;charger automatiquement &lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend&lt;/code&gt; d&#233;termine le loader (hf, hf_local, mistral_api, etc.) &lt;/li&gt;
&lt;li&gt;&lt;code&gt;device&lt;/code&gt; peut &#234;tre &lt;code&gt;cpu&lt;/code&gt;, &lt;code&gt;cuda&lt;/code&gt;, ou &lt;code&gt;null&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;api_key&lt;/code&gt; est utilis&#233; uniquement pour les backends API &lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Comment &#233;crire &lt;code&gt;services.json&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Voici la version minimale, conforme &#224; v200 :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#034;daemon&#034;: { &#034;host&#034;: &#034;127.0.0.1&#034;, &#034;port&#034;: XXX }, &#034;services&#034;: [ { &#034;name&#034;: &#034;llm.server&#034;, &#034;class&#034;: &#034;runtime_v21.services.llm.llm_server.LlmServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;slm.server&#034;, &#034;class&#034;: &#034;runtime_v21.services.llm.slm_server.SlmServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;memory.server&#034;, &#034;class&#034;: &#034;runtime_v21.services.memory_manager.MemoryManager&#034;, &#034;params&#034;: {} } ], &#034;index&#034;: { &#034;loader&#034;: { &#034;class&#034;: &#034;runtime_v21.services.index.loaders.loader_manager.ThemeIndexLoaderManager&#034;, &#034;params&#034;: {} }, &#034;reserved_ram&#034;: 100000000 }
}, &#034;tokenizer&#034;: { &#034;model_name&#034;: &#034;mistralai/Mixtral-8x7B-Instruct-v0.1&#034;, &#034;backend&#034;: &#034;hf&#034;, &#034;model_type&#034;: &#034;tokenizer&#034;, &#034;device&#034;: &#034;cpu&#034; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;R&#232;gles :&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Aucun service ne doit recevoir de mod&#232;le&lt;/strong&gt;&lt;br /&gt;
&#8594; pas de &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;model_name&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;, &lt;code&gt;device&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les services doivent recevoir uniquement :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;des noms de services Pyro5 (pour RPC)&lt;/li&gt;
&lt;li&gt;des param&#232;tres m&#233;tier (rare)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les services doivent r&#233;cup&#233;rer les mod&#232;les via &lt;code&gt;AppSettings&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. R&#233;sum&#233;&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&#201;l&#233;ment&lt;/th&gt;
&lt;th&gt;R&#244;le&lt;/th&gt;
&lt;th&gt;Contenu&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;models.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;D&#233;crit les mod&#232;les&lt;/td&gt;
&lt;td&gt;model_name, backend, device, path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ModelsConfigurator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Construit les mod&#232;les&lt;/td&gt;
&lt;td&gt;HF, API, local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AppSettingsManager&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stocke les mod&#232;les&lt;/td&gt;
&lt;td&gt;AppSettings.embedding, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;services.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;D&#233;crit les services&lt;/td&gt;
&lt;td&gt;classes, RPC, d&#233;pendances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Services Pyro5&lt;/td&gt;
&lt;td&gt;Consomment les mod&#232;les&lt;/td&gt;
&lt;td&gt;via AppSettings&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Protocoles des API LLM </title>
		<link>https://ia.dnc.global/Protocoles-des-API-LLM.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Protocoles-des-API-LLM.html</guid>
		<dc:date>2026-06-16T08:12:06Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Ce document d&#233;crit les deux modes d'appel aux API utilis&#233;s par les mod&#232;les LLM dans l'architecture v200 : synchrone et streaming. Protocoles d'appel LLM : synchrone vs streaming &lt;br class='autobr' /&gt;
Ce document d&#233;crit les deux modes d'appel utilis&#233;s par les mod&#232;les LLM dans l'architecture v200 : appel synchrone (generate) appel en streaming (stream_generate) &lt;br class='autobr' /&gt;
Les deux modes utilisent HTTP(S), mais pas le m&#234;me protocole. &lt;br class='autobr' /&gt;
Dans la v200, les InternalLLM sont les seules classes responsables : de la configuration backend (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-et-traitements-.html" rel="directory"&gt;Architecture et traitements&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Ce document d&#233;crit les deux modes d'appel aux API utilis&#233;s par les mod&#232;les LLM dans l'architecture v200 : synchrone et streaming.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;h1&gt;Protocoles d'appel LLM : synchrone vs streaming&lt;/h1&gt;
&lt;p&gt;Ce document d&#233;crit les deux modes d'appel utilis&#233;s par les mod&#232;les LLM dans l'architecture v200 :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;appel synchrone (&lt;code&gt;generate&lt;/code&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;appel en streaming (&lt;code&gt;stream_generate&lt;/code&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les deux modes utilisent HTTP(S), mais &lt;strong&gt;pas le m&#234;me protocole&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dans la v200, &lt;strong&gt;les InternalLLM sont les seules classes responsables&lt;/strong&gt; :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;de la configuration backend (client, mod&#232;le, URL si HTTP)&lt;/li&gt;
&lt;li&gt;de l'appel synchrone&lt;/li&gt;
&lt;li&gt;de l'appel streaming&lt;/li&gt;
&lt;li&gt;de la normalisation des r&#233;ponses&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. Appel synchrone : HTTP POST classique&lt;/h2&gt;
&lt;p&gt;L'appel synchrone (&lt;code&gt;generate&lt;/code&gt;) utilise un &lt;strong&gt;POST HTTP standard&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Caract&#233;ristiques&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Une seule requ&#234;te&lt;/li&gt;
&lt;li&gt;Une seule r&#233;ponse&lt;/li&gt;
&lt;li&gt;Format JSON complet&lt;/li&gt;
&lt;li&gt;Pas de flux&lt;/li&gt;
&lt;li&gt;Pas de tokens interm&#233;diaires&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Exemple (OpenAI/Mistral-like)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;POST /v1/chat/completions
Content-Type: application/json { &#034;model&#034;: &#034;mistral-large&#034;, &#034;messages&#034;: [...]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;R&#233;ponse :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;200 OK
Content-Type: application/json { &#034;id&#034;: &#034;...&#034;, &#034;choices&#034;: [ { &#034;message&#034;: { &#034;content&#034;: &#034;r&#233;ponse compl&#232;te&#034; } } ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2. Appel streaming : HTTP POST + protocole de flux&lt;/h2&gt;
&lt;p&gt;L'appel &lt;code&gt;stream_generate&lt;/code&gt; utilise &#233;galement un &lt;strong&gt;POST HTTP&lt;/strong&gt;, mais la r&#233;ponse n'est pas un JSON unique.&lt;br /&gt;
Le serveur envoie un &lt;strong&gt;flux d'&#233;v&#233;nements&lt;/strong&gt; ou de &lt;strong&gt;chunks&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Deux protocoles sont utilis&#233;s selon les backends :&lt;/p&gt;
&lt;h2&gt;2.1. SSE (Server-Sent Events)&lt;/h2&gt;
&lt;p&gt;C'est le protocole utilis&#233; par :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;OpenAI &lt;/li&gt;
&lt;li&gt;Mistral &lt;/li&gt;
&lt;li&gt;Anthropic &lt;/li&gt;
&lt;li&gt;Groq &lt;/li&gt;
&lt;li&gt;LM Studio (mode OpenAI)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Caract&#233;ristiques&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;Content-Type: text/event-stream&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Transfer-Encoding: chunked&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chaque ligne commence par &lt;code&gt;data:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chaque &#233;v&#233;nement contient un fragment (&lt;code&gt;delta&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Le flux se termine par &lt;code&gt;data: [DONE]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Exemple&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;data: {&#034;choices&#034;:[{&#034;delta&#034;:{&#034;content&#034;:&#034;Bon&#034;}}]}
data: {&#034;choices&#034;:[{&#034;delta&#034;:{&#034;content&#034;:&#034;jour&#034;}}]}
data: {&#034;choices&#034;:[{&#034;delta&#034;:{&#034;content&#034;:&#034; !&#034;}}]}
data: [DONE]&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2.2. Chunked Transfer Encoding (Ollama)&lt;/h2&gt;
&lt;p&gt;Ollama n'utilise pas SSE mais un flux de &lt;strong&gt;JSON successifs&lt;/strong&gt;, un par chunk.&lt;/p&gt;
&lt;h3&gt;Exemple&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;{&#034;response&#034;: &#034;Bon&#034;}
{&#034;response&#034;: &#034;jour&#034;}
{&#034;response&#034;: &#034; Bertrand&#034;}
{&#034;done&#034;: true}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Caract&#233;ristiques&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Pas de &lt;code&gt;data:&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pas de SSE&lt;/li&gt;
&lt;li&gt;Chaque chunk est un JSON ind&#233;pendant&lt;/li&gt;
&lt;li&gt;Le client doit lire le flux chunk par chunk&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Pourquoi deux protocoles diff&#233;rents ?&lt;/h2&gt;
&lt;p&gt;Parce que :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;un appel synchrone renvoie &lt;strong&gt;une r&#233;ponse compl&#232;te&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;un streaming renvoie &lt;strong&gt;un flux de tokens&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;HTTP classique ne permet pas d'envoyer plusieurs r&#233;ponses successives.&lt;br /&gt;
Les serveurs utilisent donc :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;SSE&lt;/strong&gt; &#8594; flux d'&#233;v&#233;nements textuels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;chunked transfer&lt;/strong&gt; &#8594; flux de JSON partiels&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebSocket&lt;/strong&gt; (rare) &#8594; flux bidirectionnel&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. Cons&#233;quences pour l'architecture v200&lt;/h2&gt;
&lt;h3&gt;4.1. &lt;code&gt;generate()&lt;/code&gt;&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;utilise un &lt;strong&gt;appel HTTP simple&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;renvoie un JSON complet&lt;/li&gt;
&lt;li&gt;normalisation effectu&#233;e dans la classe LLM&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4.2. &lt;code&gt;stream_generate()&lt;/code&gt;&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;utilise &lt;strong&gt;SSE&lt;/strong&gt; ou &lt;strong&gt;chunked transfer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;lit les fragments au fur et &#224; mesure&lt;/li&gt;
&lt;li&gt;normalise chaque fragment en format v200 :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;{ &#034;delta&#034;: &#034;texte&#034; }
...
{ &#034;delta&#034;: &#034;&#034;, &#034;meta&#034;: {...} }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Retourne un flux de chunks repr&#233;sentant la r&#233;ponse en streaming.
Contrat de l'interface :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;La m&#233;thode doit produire un it&#233;rable de chunks.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Convention v200 (obligatoire pour toutes les impl&#233;mentations) :
- Les chunks interm&#233;diaires sont des dicts contenant : { &#034;delta&#034;: &#034;&lt;texte incr&#233;mental&gt;&#034; }
- Le dernier chunk contient en plus des m&#233;tadonn&#233;es : { &#034;delta&#034;: &#034;&#034;, &#034;meta&#034;: {...} } Cette convention garantit un format standardis&#233; pour toutes les
impl&#233;mentations InternalLLM, ind&#233;pendamment du backend utilis&#233;.&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5. R&#233;sum&#233;&lt;/h2&gt;
&lt;p&gt;| Mode | Protocole | Format | Usage |
| &lt;code&gt;generate()&lt;/code&gt; | HTTP POST classique | JSON complet | r&#233;ponse unique |
| &lt;code&gt;stream_generate&lt;/code&gt; | SSE ou chunked transfer | flux de tokens | streaming |&lt;/p&gt;
&lt;h2&gt;6. Exemple&lt;/h2&gt;&lt;div class=&#034;coloration_code code&#034;&gt;&lt;div class=&#034;spip_python code&#034;&gt;&lt;div class=&#034;python&#034;&gt;&lt;ol&gt;&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;from&lt;/span&gt; commons.&lt;span style=&#034;color: black;&#034;&gt;models&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;internal&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;base&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;import&lt;/span&gt; BaseGenerativeModel&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;from&lt;/span&gt; commons.&lt;span style=&#034;color: black;&#034;&gt;models&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;response&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;import&lt;/span&gt; Response&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;class&lt;/span&gt; MistralAPIInternalLLM&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;BaseGenerativeModel&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Impl&#233;mentation Mistral API pour v200.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Cette classe contient :&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - la configuration backend (client, mod&#232;le)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - generate() : appel synchrone&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - stream_generate() : appel SSE&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - normalisation des r&#233;ponses&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; &#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;def&lt;/span&gt; &lt;span style=&#034;color: #0000cd;&#034;&gt;__init__&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; client&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; model_name: &lt;span style=&#034;color: #008000;&#034;&gt;str&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;client&lt;/span&gt; &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; client&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;model_name&lt;/span&gt; &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; model_name&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;def&lt;/span&gt; generate&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; prompt: &lt;span style=&#034;color: #008000;&#034;&gt;str&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; **kwargs&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt; -&lt;span style=&#034;color: #66cc66;&#034;&gt;&gt;&lt;/span&gt; Response:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Appel synchrone : requ&#234;te HTTP compl&#232;te, pas de streaming.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Le format exact de la r&#233;ponse d&#233;pend du backend.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; &#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; raw &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;client&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;chat&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;completions&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;create&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; model&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;model_name&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; messages&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;role&#034;&lt;/span&gt;: &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;user&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;content&#034;&lt;/span&gt;: prompt&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; stream&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;False&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; **kwargs&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;try&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; text &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; raw&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;choices&#034;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: #ff4500;&#034;&gt;0&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;message&#034;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;content&#034;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;except&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;Exception&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; text &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;str&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;raw&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;return&lt;/span&gt; Response&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; response&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;text&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; raw_response&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;raw&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; source_nodes&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; metadata&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;def&lt;/span&gt; stream_generate&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; prompt: &lt;span style=&#034;color: #008000;&#034;&gt;str&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; **kwargs&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Retourne un flux de chunks.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Le format exact d&#233;pend de l'impl&#233;mentation.&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; Convention interne v200 :&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - chunks interm&#233;diaires : {&#034;delta&#034;: &#034;...&#034;}&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; - chunk final : {&#034;delta&#034;: &#034;&#034;, &#034;meta&#034;: {...}}&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt; &#034;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; stream &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;client&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;chat&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;completions&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;create&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; model&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;self&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;model_name&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; messages&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;role&#034;&lt;/span&gt;: &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;user&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;content&#034;&lt;/span&gt;: prompt&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; stream&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #008000;&#034;&gt;True&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; **kwargs&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; final_message &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;for&lt;/span&gt; &lt;span style=&#034;color: #dc143c;&#034;&gt;chunk&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;in&lt;/span&gt; stream:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; delta &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;if&lt;/span&gt; &lt;span style=&#034;color: #dc143c;&#034;&gt;chunk&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;choices&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; c &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; &lt;span style=&#034;color: #dc143c;&#034;&gt;chunk&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;choices&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&#034;color: #ff4500;&#034;&gt;0&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#93;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;if&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;getattr&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;c&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;delta&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;and&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;getattr&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;c.&lt;span style=&#034;color: black;&#034;&gt;delta&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;content&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; delta &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; c.&lt;span style=&#034;color: black;&#034;&gt;delta&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;content&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;or&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;if&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;getattr&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;c&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;message&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; &lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; final_message &lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt; c.&lt;span style=&#034;color: black;&#034;&gt;message&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;yield&lt;/span&gt; &lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;delta&#034;&lt;/span&gt;: delta&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;yield&lt;/span&gt; &lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;delta&#034;&lt;/span&gt;: &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;&#034;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;meta&#034;&lt;/span&gt;: &lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;raw_response&#034;&lt;/span&gt;: final_message&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;nodes&#034;&lt;/span&gt;: &lt;span style=&#034;color: #008000;&#034;&gt;None&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;metadata&#034;&lt;/span&gt;: &lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class='download code_download'&gt;&lt;a href='https://ia.dnc.global/local/cache-code/07a1958561fb31461b02b12920adbad1.txt'&gt;T&#233;l&#233;charger&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Orchestration : ReAct et Backtracking</title>
		<link>https://ia.dnc.global/Orchestration-ReAct-et-Backtracking.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Orchestration-ReAct-et-Backtracking.html</guid>
		<dc:date>2026-05-17T10:04:49Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Une boucle ReAct &#034;Raisonne&#034; en marche avant, selon une suite d'&#233;tapes successives. Si le raisonnement &#233;choue &#224; donner une r&#233;ponse &#224; la question pos&#233;e, la boucle s'arr&#234;te sans r&#233;ponse. M&#234;me si une r&#233;ponse est trouv&#233;e, elle n'a pas &#233;t&#233; &#233;labor&#233;e par l'exploration de plusieurs branches : le r&#233;sultat reste non exhaustif. Cet article d&#233;crit comment on pourrait revenir en arri&#232;re et recommencer sur une hypoth&#232;se diff&#233;rente (backtracking), &#224; la fa&#231;on d'un moteur d'inf&#233;rences. &lt;br class='autobr' /&gt;
Nous proposons une architecture dans (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-ReAct-first-Neuro-symbolique-.html" rel="directory"&gt;Architecture ReAct-first Neuro-symbolique&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Une boucle ReAct &#034;Raisonne&#034; en marche avant, selon une suite d'&#233;tapes successives. Si le raisonnement &#233;choue &#224; donner une r&#233;ponse &#224; la question pos&#233;e, la boucle s'arr&#234;te sans r&#233;ponse. M&#234;me si une r&#233;ponse est trouv&#233;e, elle n'a pas &#233;t&#233; &#233;labor&#233;e par l'exploration de plusieurs branches : le r&#233;sultat reste non exhaustif.&lt;br class='autobr' /&gt;
Cet article d&#233;crit comment on pourrait revenir en arri&#232;re et recommencer sur une hypoth&#232;se diff&#233;rente (backtracking), &#224; la fa&#231;on d'un moteur d'inf&#233;rences.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;p&gt;Nous proposons une architecture dans laquelle ReAct (Reasoning + Acting) est accompagn&#233; par un Superviseur qui peut remonter l'arbre de d&#233;cisions (&#034;backtracking&#034;) et explorer des alternatives en cas d'&#233;chec ou d'insatisfaction. Dans cette approche, le superviseur serait &lt;strong&gt;un m&#233;ta-contr&#244;leur&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Un &lt;strong&gt;moteur d'inf&#233;rences logiques peut jouer un r&#244;le central dans l'orchestration&lt;/strong&gt; des actions et des d&#233;cisions &#224; suivre en cas d'&#233;chec. &lt;br class='autobr' /&gt;
En effet, un moteur logique excelle dans :
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; la d&#233;tection de situations complexes,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; la repr&#233;sentation d&#233;clarative (&#034;symbolique&#034;) de r&#232;gles, de contraintes et d'alternatives ,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; le raisonnement sur des violations et des exceptions,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; le retour en arri&#232;re (backtracking) dans un arbre de solutions pour explorer les alternatives.&lt;/p&gt;
&lt;p&gt;L'approche d&#233;velopp&#233;e &#8212; ReAct + Inf&#233;rence logique &#8212; se distingue nettement de tout ce qui existe aujourd'hui :&lt;/p&gt;
&lt;p&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; elle est &lt;strong&gt;originale&lt;/strong&gt;,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; elle est &lt;strong&gt;techniquement solide&lt;/strong&gt;,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; elle r&#233;pond &#224; un besoin &lt;strong&gt;non couvert&lt;/strong&gt; par les architectures actuelles,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; elle combine deux mondes rarement r&#233;unis : &lt;br class='autobr' /&gt; &lt;strong&gt;agents LLM&lt;/strong&gt; et &lt;strong&gt;moteurs logiques d&#233;terministes&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Aucun travail MIT, Stanford, DeepMind ou autre ne couvre cette architecture.&lt;/p&gt;
&lt;p&gt;La version v2 de ReActEngine (en d&#233;veloppement) est fond&#233; sur cette architecture. Un moteur ReAct complet, en streaming enti&#232;rement &#233;crit &#224; la main, sans LlamaIndex ou autre, avec un LLM de Mistral AI : Made in France, cocorico !&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Comment ReActAgent s'ins&#232;re dans le Workflow LlamaIndex</title>
		<link>https://ia.dnc.global/Comment-ReActAgent-s-insere-dans-le-Workflow-LlamaIndex.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Comment-ReActAgent-s-insere-dans-le-Workflow-LlamaIndex.html</guid>
		<dc:date>2026-04-13T10:15:10Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Dans LlamaIndex, la boucle ReAct repose sur un principe simple : le workflow orchestre, l'agent raisonne. &#192; chaque appel, g&#233;n&#232;re un prompt, interroge le LLM, reconstruit une &#233;tape de raisonnement et laisse le finalizer d&#233;cider de la suite. Une m&#233;canique minimale c&#244;t&#233; workflow, une intelligence maximale c&#244;t&#233; agent. &lt;br class='autobr' /&gt; #La boucle de raisonnement ReAct &lt;br class='autobr' /&gt;
##Comment `ReActAgent` s'ins&#232;re dans le Workflow LlamaIndex &lt;br class='autobr' /&gt;
LlamaIndex ReActAgent, construit sur Workflow, fournit le code du **step** dans un workflow. (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-Architecture-et-traitements-.html" rel="directory"&gt;Architecture et traitements&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Dans LlamaIndex, la boucle ReAct repose sur un principe simple : le workflow orchestre, l'agent raisonne. &#192; chaque appel, g&#233;n&#232;re un prompt, interroge le LLM, reconstruit une &#233;tape de raisonnement et laisse le finalizer d&#233;cider de la suite. Une m&#233;canique minimale c&#244;t&#233; workflow, une intelligence maximale c&#244;t&#233; agent.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;h1&gt;La boucle de raisonnement ReAct&lt;/h1&gt;
&lt;h2&gt;Comment &lt;code&gt;ReActAgent&lt;/code&gt; s'ins&#232;re dans le Workflow LlamaIndex&lt;/h2&gt;
&lt;p&gt;LlamaIndex ReActAgent, construit sur Workflow, fournit le code du &lt;strong&gt;step&lt;/strong&gt; dans un workflow. Le workflow appelle :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;BaseAgent.run_agent_step() &#8594; ReActAgent.take_step()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Donc :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;le workflow = &lt;strong&gt;chef d'orchestre&lt;/strong&gt; (encore un !)&lt;/li&gt;
&lt;li&gt;l'agent = &lt;strong&gt;une &#233;tape du workflow&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;take_step()&lt;/code&gt; = &lt;strong&gt;la logique ReAct pour une &#233;tape&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Comment sont construites les steps ReAct ?&lt;/h2&gt;
&lt;p&gt;En v&#233;rit&#233; : Le Workflow ne construit pas des steps ReAct. C'est ReActAgent qui les fait construire par le LLM.
Le Workflow ne fait que :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;appeler &lt;code&gt;take_step()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;attendre un &lt;code&gt;AgentStepOutput&lt;/code&gt; (Thought, Action, Action Input ...)&lt;/li&gt;
&lt;li&gt;d&#233;cider avec ReActFinalizer si une nouvelle &#233;tape doit &#234;tre ex&#233;cut&#233;e&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Voici ce qui se passe dans &lt;code&gt;ReActAgent.take_step()&lt;/code&gt; pour construire une &#233;tape :&lt;/p&gt;
&lt;h3&gt;&#201;tape 1 &#8212; Construire le prompt ReAct&lt;/h3&gt;
&lt;p&gt;L'agent g&#233;n&#232;re le prompt ReAct qui fixe les r&#232;gles que devra suivre le LLM pour &#233;laborer les THOUGHT, ACTION et ACTION INPUT, pour appeler les outils etc. Le prompt contient &#233;galement l'historique des &#233;changes et, in fine, la question de l'utilisateur. Voici un exemple tr&#232;s na&#239;f :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;You are a ReAct agent.
First, think step-by-step and write:
THOUGHT:
Then, if needed, write:
ACTION:
ACTION INPUT:
&lt;context&gt;
&lt;query&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&#201;tape 2 &#8212; Appeler le LLM&lt;/h3&gt;
&lt;p&gt;L'agent appelle :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;llm.stream(prompt)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Le LLM g&#233;n&#232;re la r&#233;ponse au prompt. &#8594; Le LLM produit progressivement, par petits fragments, les &lt;strong&gt;deltas&lt;/strong&gt;. &lt;/p&gt;
&lt;h3&gt;&#201;tape 3 &#8212; Le parser reconstruit les blocs&lt;/h3&gt;
&lt;p&gt;Le &lt;code&gt;ReActStreamParser&lt;/code&gt; transforme les deltas en blocs :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;THOUGHT: ...
ACTION: ...
OBSERVATION: ...
...
FINAL_ANSWER: ...&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&#201;tape 4 &#8212; Le ReActFinalizer d&#233;cide si l'&#233;tape est termin&#233;e&lt;/h3&gt;
&lt;p&gt;Le finalizer :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;valide les blocs&lt;/li&gt;
&lt;li&gt;d&#233;tecte les erreurs&lt;/li&gt;
&lt;li&gt;emp&#234;che les boucles&lt;/li&gt;
&lt;li&gt;d&#233;cide si une nouvelle &#233;tape doit &#234;tre lanc&#233;e&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&#201;tape 5 &#8212; Le workflow relance &lt;code&gt;take_step()&lt;/code&gt; si n&#233;cessaire&lt;/h3&gt;
&lt;p&gt;Si le finalizer dit &#8220;continue&#8221;, alors :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;workflow &#8594; BaseAgent.run_agent_step &#8594; ReActAgent.take_step()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et une nouvelle &#233;tape ReAct est produite.&lt;/p&gt;
&lt;h3&gt;En r&#233;sum&#233; : r&#244;le du Workflow&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Le workflow LlamaIndex ne fait qu'appeler &lt;code&gt;take_step()&lt;/code&gt; en boucle.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ReActAgent.take_step()&lt;/code&gt; g&#233;n&#232;re une &lt;em&gt;&#233;tape ReAct&lt;/em&gt; en appelant le LLM.&lt;/li&gt;
&lt;li&gt;Le &lt;code&gt;ReActStreamParser&lt;/code&gt; reconstruit les blocs ReAct &#224; partir des deltas.&lt;/li&gt;
&lt;li&gt;Le &lt;code&gt;ReActFinalizer&lt;/code&gt; d&#233;cide si une nouvelle &#233;tape doit &#234;tre lanc&#233;e.&lt;/li&gt;
&lt;li&gt;Le workflow relance &lt;code&gt;take_step()&lt;/code&gt; si n&#233;cessaire.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class='spip_document_26 spip_documents spip_documents_center'&gt;
&lt;img src='https://ia.dnc.global/local/cache-vignettes/L428xH753/bouclereact_1-e5172.png?1776293294' width='428' height='753' alt=&#034;&#034; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Voyez aussi :&lt;/strong&gt;
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; &lt;a href='https://ia.dnc.global/ReActEngine-v1-Modules-et-traitements.html' class='spip_in'&gt;ReActEngine v1 : Modules et traitements&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>ReActEngine v1 : Finalizer et StreamParser</title>
		<link>https://ia.dnc.global/Architecture-ReAct-Finalizer-et-StreamParser.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Architecture-ReAct-Finalizer-et-StreamParser.html</guid>
		<dc:date>2026-04-13T09:34:02Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Les modules ReActFinalizer, ReActStreamParser, font partie du niveau sup&#233;rieur ou &#034;Orchesrtrateur&#034; du traitement. Ils ont &#233;t&#233; d&#233;velopp&#233;s sp&#233;cialement pour atteindre les objectifs du ReActEngine v1. Architecture ReAct : Finalizer et StreamParser R&#244;les et responsabilit&#233;s ReActStreamParser &lt;br class='autobr' /&gt;
Fait le lien entre le niveau applicatif et le ReActEngine. &lt;br class='autobr' /&gt;
Responsable de : La segmentation du flux brut en blocs ReActBlock L'identification du type de chaque bloc (ReActType) La gestion du buffer et du flush (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-ReActEngine-v1-.html" rel="directory"&gt;ReActEngine v1&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Les modules ReActFinalizer, ReActStreamParser, font partie du niveau sup&#233;rieur ou &#034;Orchesrtrateur&#034; du traitement. Ils ont &#233;t&#233; d&#233;velopp&#233;s sp&#233;cialement pour atteindre les objectifs du &lt;a href='https://ia.dnc.global/ReActEngine-v1-Modules-et-traitements.html' class='spip_in'&gt;ReActEngine v1&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;h1&gt;Architecture ReAct : Finalizer et StreamParser&lt;/h1&gt;
&lt;h2&gt;R&#244;les et responsabilit&#233;s&lt;/h2&gt;
&lt;h3&gt;ReActStreamParser&lt;/h3&gt;
&lt;p&gt;Fait le lien entre le niveau applicatif et le ReActEngine.&lt;/p&gt;
&lt;p&gt;Responsable de :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;La segmentation du flux brut en blocs &lt;code&gt;ReActBlock&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'identification du type de chaque bloc (&lt;code&gt;ReActType&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La gestion du buffer et du flush final&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La conservation de l'historique des blocs extraits&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ne d&#233;cide jamais de l'arr&#234;t ou de la modification du raisonnement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Expose :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;has_final_answer()&lt;/code&gt; : indique si un bloc &lt;code&gt;FINAL_ANSWER&lt;/code&gt; est pr&#233;sent dans les blocs extraits&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;get_final_answer()&lt;/code&gt; : retourne le contenu du dernier bloc &lt;code&gt;FINAL_ANSWER&lt;/code&gt; si pr&#233;sent&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ReActFinalizer&lt;/h3&gt;
&lt;p&gt;Responsable de :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;L'orchestration du raisonnement jusqu'&#224; r&#233;solution&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'arr&#234;t du flux d&#232;s qu'un bloc de type &lt;code&gt;FINAL_ANSWER&lt;/code&gt;, &lt;code&gt;ANSWER&lt;/code&gt;, &lt;code&gt;RESPONSE&lt;/code&gt; ou &lt;code&gt;CONCLUSION&lt;/code&gt; est rencontr&#233;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La d&#233;tection de boucles ou d'anomalies de raisonnement, avec relance du raisonnement via un &lt;a href='https://ia.dnc.global/ReActEngine-v1-traitement-des-erreurs.html' class='spip_in'&gt;Thought inject&#233;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ne conna&#238;t pas l'&#233;tat interne du parser.&lt;/strong&gt; Il ne peut pas appeler &lt;code&gt;parser.has_final_answer()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;R&#232;gle de s&#233;paration stricte&lt;/h2&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Le &lt;code&gt;Finalizer&lt;/code&gt; ne doit pas inspecter &lt;code&gt;parser.blocks&lt;/code&gt; ni utiliser ses m&#233;thodes internes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le &lt;code&gt;Parser&lt;/code&gt; ne doit pas d&#233;cider de l'arr&#234;t ou la modification du raisonnement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La d&#233;tection de la r&#233;solution se fait uniquement dans le &lt;code&gt;Finalizer&lt;/code&gt;, en fonction du type des blocs yield&#233;s.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Exemple de flux&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#034;language-text&#034;&gt;Thought: I need to search.
Action: search[weather]
Observation: It's raining.
Final Answer: Bring an umbrella.&lt;/code&gt;&lt;/pre&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Le &lt;code&gt;Parser&lt;/code&gt; extrait 4 blocs typ&#233;s.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le &lt;code&gt;Finalizer&lt;/code&gt; s'arr&#234;te d&#232;s r&#233;ception du bloc &lt;code&gt;FINAL_ANSWER&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;La classe &lt;code&gt;ReActType&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;H&#233;ritage :&lt;/strong&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;class ReActType(str, Enum):&lt;/code&gt;&lt;/pre&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;H&#233;rite de &lt;code&gt;str&lt;/code&gt; pour permettre des comparaisons directes avec des cha&#238;nes (&lt;code&gt;block.type == &#034;thought&#034;&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;H&#233;rite de &lt;code&gt;Enum&lt;/code&gt; pour garantir l'&#233;num&#233;ration stricte des types.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Types ReAct fondamentaux&lt;/strong&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;R&#244;le dans le flux ReAct&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;THOUGHT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raisonnement interne&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ACTION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Appel d'outil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OBSERVATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;R&#233;sultat d'outil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FINAL_ANSWER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cl&#244;ture explicite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ANSWER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;R&#233;ponse directe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RESPONSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Variante de r&#233;ponse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CONCLUSION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cl&#244;ture synth&#233;tique&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TOOL_CALL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Appel structur&#233; (optionnel)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TOOL_RESULT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;R&#233;sultat structur&#233;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UNKNOWN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Valeur de secours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;3. &lt;strong&gt;Coh&#233;rence avec les finalizers et parsers&lt;/strong&gt;&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Les types &lt;code&gt;FINAL_ANSWER&lt;/code&gt;, &lt;code&gt;ANSWER&lt;/code&gt;, &lt;code&gt;RESPONSE&lt;/code&gt;, &lt;code&gt;CONCLUSION&lt;/code&gt; sont utilis&#233;s comme &lt;strong&gt;types de cl&#244;ture&lt;/strong&gt; dans le &lt;code&gt;Finalizer&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les types &lt;code&gt;TOOL_CALL&lt;/code&gt; et &lt;code&gt;TOOL_RESULT&lt;/code&gt; sont utiles pour des flux structur&#233;s (JSON, agents avanc&#233;s).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;UNKNOWN&lt;/code&gt; est une bonne pratique pour la robustesse du parsing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Pourquoi deux parsers ?&lt;/h1&gt;
&lt;p&gt;Les parsers ont pour fonction d'assembler un flux de r&#233;ponse brut (les tokens) en messages typ&#233;s ReAct.&lt;/p&gt;
&lt;p&gt;Les lecteurs attentifs auront remarqu&#233; que :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;il existe un ReActOutputParser directement &#224; la sortie du LLM et, pourtant, ReActEngine &#233;met un flux brut de token ;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;l'application cliente doit reconstruire les messages ReAct, par exemple avec StreamlitChatTracer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voici la distinction essentielle &#8212; et pourquoi elle est &lt;strong&gt;n&#233;cessaire&lt;/strong&gt; &#8212; entre :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActOutputParser&lt;/strong&gt; (c&#244;t&#233; LLM, logique interne de l'agent)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActEngine / Workflow&lt;/strong&gt; (c&#244;t&#233; runtime, flux brut de tokens)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;StreamlitChatTracer / client&lt;/strong&gt; (c&#244;t&#233; application, reconstruction des messages)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;dl class='spip_document_29 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/reactengine_2parser_diagram_20260408.png' class=&#034;mediabox&#034; title=&#034;Deux parser en parall&#232;le avec des objectifs et une temporalit&#233; diff&#233;rents&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH282/reactengine_2parser_diagram_20260408-cd6fe.png?1776303650' width='500' height='282' alt=&#034;PNG - 1.3&#160;Mo&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;dt class='crayon document-titre-29 spip_doc_titre' style='width:350px;'&gt; &lt;a href='https://ia.dnc.global/doc'&gt;Deux parser en parall&#232;le avec des objectifs et une temporalit&#233; diff&#233;rents &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;h2&gt;&lt;strong&gt;1. Le ReActOutputParser n'est &lt;em&gt;pas&lt;/em&gt; utilis&#233; pendant le streaming&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;ReActOutputParser&lt;/strong&gt; est con&#231;u pour analyser &lt;strong&gt;un bloc complet&lt;/strong&gt; de texte produit par le LLM, contenant typiquement :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Thought: ...
Action: tool_name
Action Input: {...}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ou bien :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Thought: ...
Answer: ...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce parser fonctionne &lt;strong&gt;uniquement&lt;/strong&gt; lorsque le LLM a fini de produire &lt;strong&gt;tout&lt;/strong&gt; le message.&lt;br /&gt;
Il ne peut pas fonctionner sur un flux token-par-token, car :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;le pattern ReAct n'est pas encore complet,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les sections Thought / Action / Observation / Answer peuvent arriver dans n'importe quel ordre,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;le LLM peut r&#233;viser sa sortie en cours de g&#233;n&#233;ration.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Donc : pendant le streaming, LlamaIndex ne peut pas appliquer ReActOutputParser.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;2. Pourquoi ReActEngine &#233;met un flux brut de tokens&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Le moteur ReAct dans LlamaIndex Workflow est con&#231;u pour :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;exposer l'int&#233;gralit&#233; du raisonnement ReAct&lt;/strong&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;permettre au client de suivre la progression en temps r&#233;el&lt;/strong&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;laisser la libert&#233; au d&#233;veloppeur de tracer, filtrer ou visualiser les &#233;tapes&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le flux brut contient donc :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;les &lt;em&gt;Thought :&lt;/em&gt; interm&#233;diaires,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les &lt;em&gt;Action :&lt;/em&gt; et &lt;em&gt;Action Input :&lt;/em&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les &lt;em&gt;Observation :&lt;/em&gt;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les &lt;em&gt;Answer :&lt;/em&gt; finales.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce flux est &lt;strong&gt;intentionnellement non structur&#233;&lt;/strong&gt;, car :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;il refl&#232;te exactement ce que le LLM produit,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;il permet d'afficher la r&#233;flexion pas &#224; pas,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;il &#233;vite d'imposer un format unique de parsing pendant le streaming.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Le moteur ne structure pas le flux, car cela casserait la transparence et la flexibilit&#233; du workflow.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;3. Pourquoi le client doit reconstruire les messages ReAct&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Comme le flux est brut, c'est &lt;strong&gt;l'application cliente&lt;/strong&gt; qui doit :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;d&#233;tecter les segments Thought / Action / Observation / Answer,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;les afficher proprement,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&#233;ventuellement les agr&#233;ger ou les filtrer,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ou les transformer en messages de chat.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour une application de chatbot fond&#233;e sur StreamLit, nous avons d&#233;velopp&#233; &lt;strong&gt;StreamlitChatTracer&lt;/strong&gt; qui a l'avantage de produire en streaming un flux d&#233;cor&#233; (police, couleur etc.).&lt;/p&gt;
&lt;p&gt;LlamaIndex fournit des helpers comme :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LlamaTrace&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;OpenInference instrumentation&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ces outils :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&#233;coutent les &#233;v&#233;nements &lt;code&gt;AgentStream&lt;/code&gt;, &lt;code&gt;ToolCall&lt;/code&gt;, &lt;code&gt;ToolCallResult&lt;/code&gt;, etc.,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;reconstruisent une vue structur&#233;e du raisonnement,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;permettent une visualisation claire dans le client.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;La reconstruction c&#244;t&#233; client est volontaire : elle permet d'adapter l'affichage au contexte (UI, logs, monitoring, etc.).&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;4. Pourquoi cette s&#233;paration est n&#233;cessaire&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;A. Le LLM produit du texte libre &#8594; pas structur&#233;&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;M&#234;me si ReAct impose un format, le LLM reste libre dans sa g&#233;n&#233;ration.&lt;br /&gt;
Le parser ne peut fonctionner qu'une fois la sortie compl&#232;te.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;B. Le streaming impose de ne pas parser pr&#233;matur&#233;ment&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Un parser ReAct ne peut pas fonctionner sur :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;un Thought incomplet,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un Action Input partiellement g&#233;n&#233;r&#233;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un Answer tronqu&#233;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;C. Le workflow doit rester g&#233;n&#233;rique&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Le moteur ReAct doit :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;fonctionner avec n'importe quel LLM,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ne pas d&#233;pendre d'un format strict,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;permettre des outils de tracing externes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;D. Le client peut choisir son mode de visualisation&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Certains veulent :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;tout afficher (Thoughts inclus),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;masquer les Thoughts,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;afficher uniquement les Tool Calls,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ou ne montrer que la r&#233;ponse finale.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Impossible de satisfaire tous les cas dans le moteur lui-m&#234;me.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;La diff&#233;rence est &lt;strong&gt;n&#233;cessaire&lt;/strong&gt; car :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActOutputParser&lt;/strong&gt; est un outil &lt;em&gt;post-hoc&lt;/em&gt; pour analyser une sortie compl&#232;te.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActEngine&lt;/strong&gt; doit fournir un flux brut pour permettre le streaming et la transparence.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Le client&lt;/strong&gt; doit reconstruire les messages ReAct selon ses besoins (UI, logs, monitoring).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cette architecture garantit :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;flexibilit&#233;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;transparence,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compatibilit&#233; avec tous les LLM,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;et contr&#244;le total c&#244;t&#233; application.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>ReActEngine v1 : traitement des erreurs</title>
		<link>https://ia.dnc.global/ReActEngine-v1-traitement-des-erreurs.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/ReActEngine-v1-traitement-des-erreurs.html</guid>
		<dc:date>2026-04-11T08:53:07Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Dans un agent de type ReAct, le raisonnement est construit &#233;tape par &#233;tape. Si une &#233;tape &#233;choue, le LLM doit avoir des informations suffisantes pour reprendre le raisonnement, ou sinon risque de s'arr&#234;ter simplement, de fa&#231;on silencieuse. L'enjeu du traitement des erreurs est de toujours fournir au LLM de quoi construire une nouvelle &#233;tape de raisonnement. Dans l'&#233;tat actuel des modules LlamaIndex, trop d'erreurs sont simplement lev&#233;es avec une classe d'exception &#034;pythonique&#034;, en dehors de tout (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-ReActEngine-v1-.html" rel="directory"&gt;ReActEngine v1&lt;/a&gt;


		</description>


 <content:encoded>&lt;div class='rss_chapo'&gt;&lt;p&gt;Dans un agent de type ReAct, le raisonnement est construit &#233;tape par &#233;tape. Si une &#233;tape &#233;choue, le LLM doit avoir des informations suffisantes pour reprendre le raisonnement, ou sinon risque de s'arr&#234;ter simplement, de fa&#231;on silencieuse.&lt;br class='autobr' /&gt;
L'enjeu du traitement des erreurs est de toujours fournir au LLM de quoi construire une nouvelle &#233;tape de raisonnement.&lt;br class='autobr' /&gt;
Dans l'&#233;tat actuel des modules LlamaIndex, trop d'erreurs sont simplement lev&#233;es avec une classe d'exception &#034;pythonique&#034;, en dehors de tout processus de reprise. C'est un probl&#232;me assez g&#233;n&#233;ral, que l'on retrouve dans les plus grands chatbots, se traduisant alors par un silence, un abandon ou un blocage.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;h1&gt;Le traitement des erreurs dans ReActEngine&lt;/h1&gt;
&lt;p&gt;Dans ReActEngine, les erreurs sont trait&#233;es de deux mani&#232;res, &#224; deux niveaux et de fa&#231;on ind&#233;pendante : les &lt;strong&gt;Exceptions&lt;/strong&gt; et les &lt;strong&gt;Thoughts inject&#233;s&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;A - Exceptions&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Pour corriger la sortie ReAct mal form&#233;e avant m&#234;me qu'elle n'entre dans le flux.
Exceptions = correction structurelle.&lt;/p&gt;
&lt;p&gt;Aucune erreur survenant au cours de l'ex&#233;cution de &lt;code&gt;take_step()&lt;/code&gt; ( ce qui inclut de nombreux modules tels que les ToolBox, MCP etc. ) ne doit lever une exception de classe g&#233;n&#233;rale. Seules deux classes d'exceptions peuvent &#234;tre utilis&#233;es, et doivent &#234;tre trait&#233;es dans ce module :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RetryException&lt;/strong&gt;
Indique qu'une erreur r&#233;cup&#233;rable s'est produite ( une r&#233;ponse du LLM incompl&#232;te ou mal form&#233;e, une erreur d'outil etc. ). La m&#234;me &#233;tape ReAct doit &#234;tre r&#233;-essay&#233;e, &#224; charge du LLM de trouver un contournement en se basant sur les indications du message d'erreur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ForceFinalizeException&lt;/strong&gt;
Indique qu'une erreur non r&#233;cup&#233;rable s'est produite ( un &#233;tat ReAct invalide, une erreur d'outil sans contournement possible etc. ) et que le LLM doit produire directement une r&#233;ponse finale.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exemple d'exception lev&#233;e par un outil : &lt;/p&gt;&lt;div class=&#034;coloration_code code&#034;&gt;&lt;div class=&#034;spip_python code&#034;&gt;&lt;div class=&#034;python&#034;&gt;&lt;ol&gt;&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;if&lt;/span&gt; date_str_s.&lt;span style=&#034;color: black;&#034;&gt;isdigit&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;raise&lt;/span&gt; RetryException&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;Invalid input: this function expects a readable date, not a timestamp, retry with ISO 8601 formats (`YYYY-MM-DD`, `YYYY-MM-DDTHH:MM:SS`).&#034;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class='download code_download'&gt;&lt;a href='https://ia.dnc.global/local/cache-code/c5b1c543d8161e21061665f4cec6bfc4.txt'&gt;T&#233;l&#233;charger&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Exemples de situations r&#233;cup&#233;rables :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Action Input manquant&lt;/li&gt;
&lt;li&gt;Thought sans Action&lt;/li&gt;
&lt;li&gt;JSON invalide&lt;/li&gt;
&lt;li&gt;protocole ReAct viol&#233;&lt;/li&gt;
&lt;li&gt;output tronqu&#233; en streaming&lt;/li&gt;
&lt;li&gt;outil mal appell&#233; ou mal utilis&#233;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans ces cas, le LLM re&#231;oit les informations n&#233;cessaires pour r&#233;g&#233;n&#233;rer une &#233;tape ReAct correcte.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;B - Thought inject&#233;&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Pour corriger le raisonnement, pas la forme. Thought = correction cognitive&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;&lt;div class=&#034;coloration_code code&#034;&gt;&lt;div class=&#034;spip_python code&#034;&gt;&lt;div class=&#034;python&#034;&gt;&lt;ol&gt;&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt;&lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;if&lt;/span&gt; block.&lt;span style=&#034;color: #008000;&#034;&gt;type&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;in&lt;/span&gt; &lt;span style=&#034;color: black;&#034;&gt;&#123;&lt;/span&gt;ReActType.&lt;span style=&#034;color: black;&#034;&gt;OBSERVATION&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt; ReActType.&lt;span style=&#034;color: black;&#034;&gt;FINAL_ANSWER&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&#125;&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;and&lt;/span&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;not&lt;/span&gt; block.&lt;span style=&#034;color: black;&#034;&gt;content&lt;/span&gt;.&lt;span style=&#034;color: black;&#034;&gt;strip&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;: &lt;span style=&#034;color: #808080; font-style: italic;&#034;&gt;#x&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;yield&lt;/span&gt; ReActBlock&lt;span style=&#034;color: black;&#034;&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #008000;&#034;&gt;type&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;ReActType.&lt;span style=&#034;color: black;&#034;&gt;THOUGHT&lt;/span&gt;&lt;span style=&#034;color: #66cc66;&#034;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; content&lt;span style=&#034;color: #66cc66;&#034;&gt;=&lt;/span&gt;&lt;span style=&#034;color: #483d8b;&#034;&gt;&#034;Je constate que je n'ai obtenu aucune r&#233;ponse. Peut-&#234;tre devrais-je v&#233;rifier les param&#232;tres ou reformuler ma demande.&#034;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: black;&#034;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li style=&#034;font-weight: normal; vertical-align:top;&#034;&gt;&lt;div style=&#034;&#034;&gt; &lt;span style=&#034;color: #ff7700;font-weight:bold;&#034;&gt;continue&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;p class='download code_download'&gt;&lt;a href='https://ia.dnc.global/local/cache-code/c3cc449d92c4344d1d025200503762ee.txt'&gt;T&#233;l&#233;charger&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Cas d'usage :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;bouclage sur un outil en erreur&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;observation vide ( pertinente ou r&#233;sultant d'une erreur )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it&#233;rations excessives&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;action r&#233;p&#233;t&#233;e&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;mod&#232;le qui &#034;tourne en rond&#034;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans ces cas, on veut reprendre le flux, pas relancer le LLM.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h2&gt;Diagramme du traitement des erreurs&lt;/h2&gt;
&lt;p&gt;Les deux modes influencent le raisonnement, mais &#224; des niveaux diff&#233;rents du pipeline.
La diff&#233;rence entre ces deux modes et leur ind&#233;pendance appara&#238;t clairement dans ce diagramme :&lt;/p&gt;
&lt;dl class='spip_document_35 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/reactagent_workflow-2026-04-11-081323.png' class=&#034;mediabox&#034; title=&#034;ReActEngine : Traitement des erreurs&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH361/reactagent_workflow-2026-04-11-081323-998b5.png?1776303652' width='500' height='361' alt=&#034;PNG - 1.5&#160;Mo&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;dt class='crayon document-titre-35 spip_doc_titre' style='width:350px;'&gt; &lt;a href='https://ia.dnc.global/doc'&gt;ReActEngine : Traitement des erreurs &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;p&gt;Les exceptions RetryException et ForceFinalizeException agissent entre 3 et 7 ( interne au ReActAgent ), l'insertion des Thoughts entre 8 et 12 ( le niveau d(orchestration par le Finalizer).&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div &lt;div class='rss_ps'&gt;&lt;p&gt;##Est-ce suffisant ?&lt;br class='autobr' /&gt;
S'agissant de la boucle ReAct (les exceptions), le traitement ne peut &#234;tre am&#233;lior&#233; sans remonter explicitement dans un arbre de raisonnement (Backtracking) en cas d'erreur.&lt;br class='autobr' /&gt;
Il s'agit de quitter ou corriger la branche courante :
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; le moteur revient &#224; un &#233;tat ant&#233;rieur du raisonnement,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; demande au mod&#232;le de r&#233;essayer une nouvelle &#233;tape de contournement.&lt;/p&gt;
&lt;p&gt;C'est d&#233;j&#224; fait partiellement via RetryException, mais ce n'est pas encore du vrai backtracking, car :
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; on n'a pas un historique structur&#233; - pas d'&#034;arborescence&#034; ni de &#034;branches&#034; - des &#233;tats (stack des ReasoningSteps)
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; on ne revient pas &#224; un &#233;tat ant&#233;rieur du raisonnement,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; on ne supprime pas la branche fautive,
&lt;br /&gt;&lt;span class=&#034;spip-puce ltr&#034;&gt;&lt;b&gt;&#8211;&lt;/b&gt;&lt;/span&gt; on ne modifie pas le contexte du mod&#232;le.&lt;/p&gt;
&lt;p&gt;*&#224; suivre...*&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>ReActEngine v1 : Modules et traitements</title>
		<link>https://ia.dnc.global/ReActEngine-v1-Modules-et-traitements.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/ReActEngine-v1-Modules-et-traitements.html</guid>
		<dc:date>2026-04-09T08:23:12Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;ReActEngine Mistral v1 est un moteur agentique modulaire, contr&#244;lable et extensible, combinant RAG (Research Augmented Generation), outils personnalis&#233;s, s&#233;lection dynamique d'outils dont MCP (Model Context Protocol) et g&#233;n&#233;ration orchestr&#233;e. Il est con&#231;u pour les environnements multi-th&#232;mes, multi-sources et n&#233;cessitant une auditabilit&#233; stricte du raisonnement et des actions. &lt;br class='autobr' /&gt; Destin&#233;e &#224; un public expert, voici une description de l'agent **ReActEngine Mistral v104** fond&#233; sur (...)&lt;/p&gt;


-
&lt;a href="https://ia.dnc.global/-ReActEngine-v1-.html" rel="directory"&gt;ReActEngine v1&lt;/a&gt;


		</description>


 <content:encoded>&lt;img class='spip_logo spip_logo_right spip_logos' alt=&#034;&#034; style='float:right' src='https://ia.dnc.global/local/cache-vignettes/L150xH103/arton68-d9178.png?1776303652' width='150' height='103' /&gt;
		&lt;div class='rss_chapo'&gt;&lt;p&gt;ReActEngine Mistral v1 est un moteur agentique modulaire, contr&#244;lable et extensible, combinant RAG (Research Augmented Generation), outils personnalis&#233;s, s&#233;lection dynamique d'outils dont MCP (Model Context Protocol) et g&#233;n&#233;ration orchestr&#233;e.&lt;br class='autobr' /&gt;
Il est con&#231;u pour les environnements multi-th&#232;mes, multi-sources et n&#233;cessitant une auditabilit&#233; stricte du raisonnement et des actions.&lt;/p&gt;&lt;/div&gt;
		&lt;div class='rss_texte'&gt;&lt;hr /&gt;
&lt;p&gt;Destin&#233;e &#224; un public expert, voici une description de l'agent &lt;strong&gt;ReActEngine Mistral v104&lt;/strong&gt; fond&#233; sur &lt;code&gt;llama_index.core.agent.workflow.ReActAgent&lt;/code&gt;, int&#233;grant Finalizer, ToolRouter, RAG, outils personnalis&#233;s et orchestration.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;ReActEngine Mistral v104 &#8212; Description technique&lt;/strong&gt;&lt;/h2&gt;
&lt;h1&gt;1. Nature de l'agent&lt;/h1&gt;
&lt;p&gt;L'agent &lt;strong&gt;Mistral ReAct v104&lt;/strong&gt; est un moteur agentique bas&#233; sur le paradigme &lt;strong&gt;ReAct (Reasoning + Acting)&lt;/strong&gt;.&lt;br /&gt;
Il combine :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;un &lt;strong&gt;LLM Mistral&lt;/strong&gt; (via API ou local),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un &lt;strong&gt;orchestrateur d'outils&lt;/strong&gt; dont MCP,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un &lt;strong&gt;Finalizer&lt;/strong&gt; pour la g&#233;n&#233;ration contr&#244;l&#233;e,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un &lt;strong&gt;ToolRouter&lt;/strong&gt; pour la s&#233;lection dynamique d'outils,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;un &lt;strong&gt;RAG&lt;/strong&gt; (Research Augmented Generation) modulaire bas&#233; sur l'agent de recherche &lt;a href='https://ia.dnc.global/Chat-Engine-Mistral.html' class='spip_in'&gt;Chat Engine Mistral&lt;/a&gt; utilis&#233; par notre ChatBot simple.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il s'appuie sur la classe &lt;strong&gt;&lt;a href='https://ia.dnc.global/Comment-ReActAgent-s-insere-dans-le-Workflow-LlamaIndex.html' class='spip_in'&gt;ReActAgent(Workflow)&lt;/a&gt;&lt;/strong&gt; plut&#244;t que sur les agents pr&#233;construits, afin de garantir :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;un contr&#244;le fin du cycle ReAct,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une meilleure auditabilit&#233;,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une int&#233;gration propre des outils personnalis&#233;s,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une compatibilit&#233; avec les pipelines agentiques complexes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Constatant que les &lt;a href='https://ia.dnc.global/ReActEngine-v1-traitement-des-erreurs.html' class='spip_in'&gt;erreurs dans la boucle ReAct&lt;/a&gt; non intercept&#233;es ou mal trait&#233;es aboutissaient sur un arr&#234;t intempestif et silencieux du raisonnement, &lt;strong&gt;un principe est pos&#233; : dans la boucle ReAct, seules deux exceptions peuvent ( et doivent ) &#234;tre lev&#233;es : RetryException et ForceFinalizeException. Le message d'erreur doit &#234;tre explicite pour permettre au raisonnement de poursuivre ou de retourner proprement vers l'utilisateur&lt;/strong&gt;.
Ceci a motiv&#233; une part des modifications au code de Llamaindex.&lt;/p&gt;
&lt;p&gt;Avec le m&#234;me objectif - &#233;viter les arr&#234;ts du raisonnement - deux autres modifications portent sur la g&#233;n&#233;ration et le traitement de &lt;strong&gt;question pos&#233;e &#224; l'utilisateur&lt;/strong&gt; ainsi que le &lt;strong&gt;recours au RAG&lt;/strong&gt; pour y trouver des informations susceptibles de guider le raisonnement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Points cl&#233;s de la version v104&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Int&#233;gration du &lt;strong&gt;Finalizer&lt;/strong&gt; (contr&#244;le de la r&#233;ponse finale).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Int&#233;gration du &lt;strong&gt;ToolRouter&lt;/strong&gt; (s&#233;lection dynamique des outils).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilisation de &lt;code&gt;ReActAgent(Workflow)&lt;/code&gt; plut&#244;t que l'agent pr&#233;construit, afin d'atteindre le c&#339;ur de la boucle ReAct et y apporter des am&#233;liorations .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Acc&#232;s du LLM au RAG avec l'outil &lt;code&gt;RagTool&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Acc&#232;s du LLM aux donn&#233;es temps r&#233;el avec MCP.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Architecture stateless c&#244;t&#233; agent, stateful c&#244;t&#233; application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gestion centralis&#233;e des erreurs assurant la &lt;strong&gt;continuit&#233; du raisonnement&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;2. Architecture g&#233;n&#233;rale&lt;/h1&gt;
&lt;h2&gt;2.1. Diagramme des &#233;changes&lt;/h2&gt;
&lt;dl class='spip_document_28 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/reactengine_diagram_20260408.png' class=&#034;mediabox&#034; title=&#034;ReActEngine v1 diagramme des &#233;changes&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH242/reactengine_diagram_20260408-0e31b.png?1776303653' width='500' height='242' alt=&#034;PNG - 774.8&#160;ko&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;dt class='crayon document-titre-28 spip_doc_titre' style='width:350px;'&gt; &lt;a href='https://ia.dnc.global/doc'&gt;ReActEngine v1 diagramme des &#233;changes &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;p&gt;Les modules de la partie gauche (ReActEngine, ToolRouter, ReActFinalizer, ReActStreamParser) ont &#233;t&#233; d&#233;velopp&#233;s sp&#233;cialement pour atteindre les objectifs du ReActEngine v1, tandis que la partie droite comprend les modules du ReActAgent(Workflow) de LlamaIndex avec quelques adaptations. Le LLM est une API de MistralAI.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Conseils : Cliquez sur le diagramme pour le zoomer. Ouvrez le diagramme dans une autre fen&#234;tre pour mieux suivre la suite.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;2.2. Vision globale du flux&lt;/h2&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Utilisateur &#8594; ReActEngine&lt;/strong&gt; : prompt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActEngine &#8594; ToolRouter&lt;/strong&gt; : s&#233;lection d'outils.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActEngine &#8594; ReActAgent&lt;/strong&gt; : initialisation du pipeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Formatter &#8594; LLM&lt;/strong&gt; : message format&#233;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;LLM &#8594; StreamParser&lt;/strong&gt; : tokens bruts &#8594; blocs ReAct.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Parser &#8594; Agent&lt;/strong&gt; : StepResult.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Workflow&lt;/strong&gt; : d&#233;cide de la suite (outil, raisonnement, final).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Finalizer&lt;/strong&gt; : rebouclage sur erreur ou r&#233;ponse finale.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ReActEngine &#8594; Utilisateur&lt;/strong&gt; : streaming de la r&#233;ponse.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A partir d'ici, nous pouvons distinguer :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;La &lt;strong&gt;boucle ReAct&lt;/strong&gt; reposant sur les modules LlamaIndex : ReActAgent, BaseWorkflowAgent, ReActWorkflow, ReActOutputParser. Seule la boucle ReAct &#233;change avec le LLM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'&lt;strong&gt;Orchestrateur&lt;/strong&gt; compos&#233; des modules de haut-niveau : ReActEngine, ToolRouter, &lt;a href='https://ia.dnc.global/Architecture-ReAct-Finalizer-et-StreamParser.html' class='spip_in'&gt;ReActFinalizer, ReActStreamParser&lt;/a&gt;. ReActAgent est le seul lien avec ce niveau applicatif.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2.3. Boucle ReAct&lt;/h2&gt;
&lt;p&gt;L'agent suit la logique d&#233;crite dans &lt;em&gt;Synergizing Reasoning and Acting in Language Models&lt;/em&gt; :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reasoning&lt;/strong&gt; : le LLM produit une intention ou un plan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Acting&lt;/strong&gt; : l'agent appelle un outil.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Observation&lt;/strong&gt; : l'outil renvoie un r&#233;sultat.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reasoning&lt;/strong&gt; : le LLM int&#232;gre l'observation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Final Answer&lt;/strong&gt; : produit par le Finalizer.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Avec LlamaIndex ReActAgent bas&#233; sur Workflow, la boucle ReAct est orchestr&#233;e par r&#233;p&#233;tition de la &lt;strong&gt;fonction take_step()&lt;/strong&gt;. Toute &lt;strong&gt;action&lt;/strong&gt; est synonyme d'&lt;strong&gt;appel &#224; un outil&lt;/strong&gt;. Il est mis fin &#224; la boucle lorsqu'une &lt;strong&gt;r&#233;ponse finale&lt;/strong&gt; est d&#233;tect&#233;e .&lt;/p&gt;
&lt;dl class='spip_document_30 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/react_boucle_diagram-2026-04-10-074714.png' class=&#034;mediabox&#034; title=&#034;La boucle ReAct&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH379/react_boucle_diagram-2026-04-10-074714-9a581.png?1776303655' width='500' height='379' alt=&#034;PNG - 613&#160;ko&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;dt class='crayon document-titre-30 spip_doc_titre' style='width:350px;'&gt; &lt;a href='https://ia.dnc.global/doc'&gt;La boucle ReAct &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;p&gt;En r&#233;sum&#233; :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Le workflow ne fait qu'appeler en boucle la m&#233;thode take_step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ReActAgent construit chaque &#233;tape en appelant le LLM.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le parser transforme les deltas en blocs ReAct.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le finalizer d&#233;cide si l'agent doit continuer ou s'arr&#234;ter.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le workflow relance l'&#233;tape tant que n&#233;cessaire.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ReActAgent (remani&#233;)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; message format&#233; (prompt + contexte + outils).&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
Impl&#233;mente la logique ReAct :&lt;br /&gt;
Thought &#8594; Action &#8594; Observation &#8594; Thought &#8594; &#8230;&lt;br /&gt;
D&#233;cide quand appeler un outil.
Produit un &lt;em&gt;StepResult&lt;/em&gt; &#224; chaque it&#233;ration.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; StepResult (structure contenant Thought/Action/Observation).&lt;/p&gt;
&lt;p&gt;Ce module est au centre du protocole ReAct. Il fournit l'infrastructure n&#233;cessaire pour traiter :
la construction des &#233;tapes de raisonnement, les appels au LLM, le parsing structur&#233; des r&#233;ponses du LLM, le d&#233;clenchement d'outils, la production de la r&#233;ponse finale.&lt;/p&gt;
&lt;p&gt;Le ReActAgent ne traite qu'une &#233;tape &#224; la fois. Il est appel&#233;, d'&#233;tape en &#233;tape, par la m&#233;thode run_agent_step du &lt;a href='https://ia.dnc.global/Comment-ReActAgent-s-insere-dans-le-Workflow-LlamaIndex.html' class='spip_in'&gt;Workflow&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;La m&#233;thode take_step()&lt;/h4&gt;
&lt;p&gt;Au c&#339;ur de la boucle ReAct, cette m&#233;thode traite une seule &#233;tape de raisonnement :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Formater l'entr&#233;e du LLM &#224; l'aide du template ReAct.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Appeler le LLM (en mode streaming ou non).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Parser la sortie du mod&#232;le en un ReasoningStep structur&#233;.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;G&#233;rer les erreurs de parsing ou les &#233;tats ReAct invalides.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Puis, selon le cas :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;retourner une r&#233;ponse finale,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;d&#233;clencher un appel d'outil,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ou &lt;em&gt;demander au LLM de r&#233;essayer&lt;/em&gt; ou de finaliser.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Les principales modifications portent sur la gestion des sorties LLM mal form&#233;es ou incompl&#232;tes, ainsi que sur le traitement des exceptions :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;normalisation du format de sortie du LLM, contribuant &#224; rendre l'agent agnostique en ce qui concerne les LLMs dont les formats sont peu normalis&#233;s.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;relance de la boucle lorsque le parseur d&#233;tecte une sortie ReAct incompl&#232;te, mal form&#233;e ou autrement invalide, mais pouvant &#234;tre corrig&#233;e par le mod&#232;le.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;traitement de deux exceptions, :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RetryException&lt;/code&gt; &#8594; la sortie est incompl&#232;te ou tronqu&#233;e ; le LLM doit
r&#233;essayer en se fondant sur le message d'erreur. Cela couvre aussi les erreurs des outils.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ForceFinalizeException&lt;/code&gt; &#8594; le mod&#232;le a produit un &#233;tat ReAct invalide
(ex. : Thought sans Action ni Answer) ; le prochain appel LLM doit produire
uniquement une r&#233;ponse finale. &lt;strong&gt;Ces exceptions sont les seules autoris&#233;es au sein de la boucle afin d'&#233;viter les arr&#234;ts silencieux de l'agent&lt;/strong&gt;. Toutes les exceptions d'une autre classe lev&#233;es au sein du code sont intercept&#233;es et ramen&#233;es &#224; l'une de ces deux exceptions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;La m&#233;thode handle_tool_call_result()&lt;/h4&gt;
&lt;p&gt;Cette m&#233;thode traite les r&#233;sultats des appels d'outils :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;r&#233;cup&#232;re l'historique courant de raisonnement (variable d'&#233;tat ctx),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;inspecte chaque r&#233;sultat d'outil,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;distingue les erreurs r&#233;elles des contenus vides l&#233;gitimes,&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;normalise le contenu observ&#233;,&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ajoute une &#233;tape d'observation au raisonnement,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;g&#232;re les cas particuliers (ask_user, return_direct),&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;met &#224; jour l'&#233;tat persistant du raisonnement dans le contexte (variable d'&#233;tat ctx).
Les principales modifications incluent :&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;la distinction entre un retour d'outil l&#233;gitimement vide et une erreur de l'outil.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;la normalisation du retour d'outil (le contenu observ&#233;), contribuant &#224; l'adaptation aux diff&#233;rents LLMs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;une d&#233;tection d'erreurs garantissant que les outils signalent explicitement leurs &#233;checs en levant l'une des exception RetryException ou ForceFinalizeException afin d'&#233;viter un arr&#234;t intempestif du raisonnement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;la gestion d'un &lt;strong&gt;outil AskUserTool&lt;/strong&gt; ( cr&#233;&#233; dans la GeneralToolBox ) permettant au mod&#232;le de poser une question &#224; l'utilisateur, puis la transformation de sa r&#233;ponse en Observation ReAct et la relance de la boucle ReAct via take_step().&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;BaseWorkflowAgent (modifi&#233;)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; StepResult ou message interm&#233;diaire.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
G&#232;re la logique g&#233;n&#233;rique d'un agent (&#233;tat, transitions, erreurs).
Coordonne les appels entre Workflow, Formatter, Parser.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; instructions pour la prochaine &#233;tape du workflow.&lt;/p&gt;
&lt;p&gt;La principale modification porte sur la gestion de la pause en attente d'une r&#233;ponse de l'utilisateur (outil AskUser).&lt;/p&gt;
&lt;h3&gt;ReActWorkflow&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; StepResult + contexte d'ex&#233;cution.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
Orchestration du cycle ReAct.
D&#233;termine si l'agent doit :&lt;br /&gt;
continuer &#224; raisonner,&lt;br /&gt;
appeler un outil,&lt;br /&gt;
ou produire la r&#233;ponse finale.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; nouvelle &#233;tape &#224; ex&#233;cuter (run_step).&lt;/p&gt;
&lt;h3&gt;ReActChatFormatter&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; prompt utilisateur + &#233;tat du workflow.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
Formate le message dans le style attendu par le LLM (system + user + tool instructions).
Injecte les outils dans le prompt si n&#233;cessaire.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; &lt;em&gt;message format&#233;&lt;/em&gt; envoy&#233; au LLM.&lt;/p&gt;
&lt;h3&gt;ReActOutputParser (modifi&#233;)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; sortie brute du LLM. &lt;strong&gt;Traitement :&lt;/strong&gt;
Analyse la r&#233;ponse du LLM.
Extrait Thought / Action / Observation / FinalAnswer.
D&#233;tecte les erreurs de format.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; StepResult structur&#233;.&lt;/p&gt;
&lt;p&gt;Les principales modifications portent sur une d&#233;tection et une gestion correcte des erreurs en levant RetryException ou ForceFinalizeException afin d'&#233;viter les arr&#234;ts intempestifs du LLM.&lt;/p&gt;
&lt;h3&gt;Mod&#232;le LLM&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; message format&#233; (prompt complet).&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
G&#233;n&#233;ration token-par-token.
Produit du texte brut sans structure interne explicite.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; tokens bruts &#8594; envoy&#233;s au StreamParser.&lt;/p&gt;
&lt;p&gt;Il faut noter que, si de nombreuses adaptations visent &#224; rendre notre ReActAgent agnostique vis-&#224;-vis des LLMs, notamment en normalisant les formats des requ&#234;tes et des r&#233;ponses, cela n'est pas encore finalis&#233; dans l'&#233;tat actuel du d&#233;veloppement.&lt;/p&gt;
&lt;h3&gt;Tool&lt;/h3&gt;
&lt;p&gt;L'agent combine trois familles d'outils :&lt;/p&gt;
&lt;h4&gt;A. RAG (QueryEngineTool)&lt;/h4&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Bas&#233; sur &lt;code&gt;chat_engine_mistral_v1.3.x&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilise les index cr&#233;&#233;s par &lt;strong&gt;RAG Manager&lt;/strong&gt; ou &lt;strong&gt;IngestCmd&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Permet un RAG coh&#233;rent, multith&#232;me, multilingue.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exposer un outil RAG &#224; la boucle ReAct permet au LLM d'acc&#233;der &#224; des descriptions syst&#233;miques, des routines de raisonnement, des sp&#233;cifications etc., tout documents normatifs permettant de soutenir le raisonnement et de le r&#233;-orienter en cas d'impasse.&lt;/p&gt;
&lt;h4&gt;B. Outils personnalis&#233;s (FunctionTools)&lt;/h4&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Fournissent des donn&#233;es &lt;strong&gt;temps r&#233;el&lt;/strong&gt; (par exemple issues de &lt;strong&gt;&lt;a href=&#034;https://thewiw.com&#034; class='spip_out' rel='external'&gt;WhatisWhat&lt;/a&gt;&lt;/strong&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Les donn&#233;es sont inject&#233;es via &lt;strong&gt;MCP&lt;/strong&gt;. Voir : &lt;a href='https://ia.dnc.global/ReAct-et-integration-des-donnees-temps-reel-avec-MCP.html' class='spip_in'&gt;ReAct et int&#233;gration des donn&#233;es temps r&#233;el avec MCP ( Model Context Protocol ) &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exemples : m&#233;t&#233;o, &#233;tat d'un syst&#232;me, donn&#233;es m&#233;tier, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voir &#233;galement : &lt;a href='https://ia.dnc.global/Classe-ChatEngine-version-1-5-x-pour-ChattyBot.html' class='spip_in'&gt;RAG : Chat Engine ReAct avec outils&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;C. Outils g&#233;n&#233;ralistes&lt;/h4&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Calculs : arithm&#233;tique, statistique&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Manipulation de texte&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Utilitaires divers&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;2.3. Orchestrateur&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;De ce point de vue, on peut consid&#233;rer le ReActEngine d&#233;crit pr&#233;c&#233;demment comme une bo&#238;te noire (dont on repr&#233;sente tout de m&#234;me l'essentiel pour une meilleure compr&#233;hension) anim&#233;e par l'Orchestrateur.&lt;/p&gt;
&lt;dl class='spip_document_32 spip_documents'&gt; &lt;dt&gt; &lt;a href='https://ia.dnc.global/IMG/png/reactengine_diagram_mermaid-2026-04-10-125932.png' class=&#034;mediabox&#034; title=&#034;Modules de haut niveau, autour de l'agent ReAct&#034; &gt; &lt;img src='https://ia.dnc.global/local/cache-vignettes/L500xH357/reactengine_diagram_mermaid-2026-04-10-125932-d4abe.png?1776303656' width='500' height='357' alt=&#034;PNG - 638.7&#160;ko&#034; /&gt; &lt;/a&gt; &lt;/dt&gt; &lt;dt class='crayon document-titre-32 spip_doc_titre' style='width:350px;'&gt; &lt;a href='https://ia.dnc.global/doc'&gt;Modules de haut niveau, autour de l'agent ReAct &lt;/a&gt; &lt;/dt&gt; &lt;/dl&gt;
&lt;h3&gt;User&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; intention humaine, question, commande.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt; aucun &#8212; c'est la source du prompt.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; &lt;em&gt;prompt utilisateur&lt;/em&gt; envoy&#233; au ReActEngine.&lt;/p&gt;
&lt;h3&gt;ToolRouter&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; prompt brut.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
Analyse s&#233;mantique du prompt.
S&#233;lectionne les outils pertinents (toolbag).&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; liste d'outils pertinents &#8594; renvoy&#233;e au ReActEngine.&lt;/p&gt;
&lt;h3&gt;ReActEngine&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; prompt utilisateur.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
D&#233;termine si le prompt n&#233;cessite des outils.
Appelle le &lt;strong&gt;ToolRouter&lt;/strong&gt; pour identifier les outils pertinents.
Initialise un agent ReAct complet (Finalizer, Workflow, Formatter, Parser&#8230;).
Lance la boucle de streaming (token-par-token).&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; flux de tokens structur&#233;s (Thought / Action / Observation / FinalAnswer).&lt;/p&gt;
&lt;h3&gt;ReActStreamParser&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; tokens bruts provenant du LLM. &lt;strong&gt;Traitement :&lt;/strong&gt;
Reconstitue les blocs ReAct (Thought, Action, Observation&#8230;).
Filtre les artefacts, nettoie les tokens.
&#201;met des fragments de r&#233;ponse via un g&#233;n&#233;rateur asynchrone.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; tokens nettoy&#233;s + blocs ReAct structur&#233;s.&lt;/p&gt;
&lt;h3&gt;ReActFinalizer&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Entr&#233;e :&lt;/strong&gt; instance d'agent ReAct.&lt;br /&gt;
&lt;strong&gt;Traitement :&lt;/strong&gt;
Surveille la fin du raisonnement.
D&#233;tecte un &lt;em&gt;FinalAnswer&lt;/em&gt; ou une condition d'arr&#234;t.
Nettoie et finalise la r&#233;ponse.&lt;br /&gt;
&lt;strong&gt;Sortie :&lt;/strong&gt; r&#233;ponse finale propre, pr&#234;te &#224; &#234;tre envoy&#233;e &#224; l'utilisateur.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;3. API du ReActEngine v1&lt;/h1&gt;
&lt;h2&gt;3.1. &lt;code&gt;__init__(...)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Deux modes d'initialisation :&lt;/p&gt;
&lt;h3&gt;Mode 1 : avec &lt;code&gt;ragkwargs&lt;/code&gt;&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Adapt&#233; &#224; une utilisation en mode API, relan&#231;ant l'instanciation &#224; chaque requ&#234;te.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le th&#232;me, la langue, le niveau de d&#233;tail, etc. sont fournis d&#232;s l'instanciation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'agent est imm&#233;diatement op&#233;rationnel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Mode 2 : sans &lt;code&gt;ragkwargs&lt;/code&gt;&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;Adapt&#233; &#224; un fonctionnement en mode daemon ou worker multi-th&#232;mes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'application doit ensuite appeler &lt;code&gt;start()&lt;/code&gt; avec le th&#232;me en argument.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Param&#232;tres cl&#233;s :&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;config&lt;/code&gt; : configuration globale (commune &#224; IngestCmd, ChattyBot, ChattyWS&#8230;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;llmapikey&lt;/code&gt; : cl&#233; API MistralAI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;token&lt;/code&gt; : jeton de s&#233;curit&#233; pour les serveurs de donn&#233;es&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ragkwargs&lt;/code&gt; : dictionnaire contenant au minimum :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;theme&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;detail&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;language&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3.2. M&#233;thode &lt;code&gt;start()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;M&#233;thode pour les services REST ou workers persistants.&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;compl&#232;te l'initialisation selon le th&#232;me,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;charge l'index si n&#233;cessaire,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;permet aux applications stateful de fournir leur propre index (optimisation),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;pr&#233;pare l'agent ReAct pour le th&#232;me courant.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Retour : &lt;strong&gt;un objet &lt;code&gt;ReActAgent&lt;/code&gt; pr&#234;t &#224; l'emploi&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;3.3. Gestion de l'historique &#8212; &lt;code&gt;set_history()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Cette m&#233;thode :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;re&#231;oit un historique &lt;strong&gt;OpenAI-style&lt;/strong&gt; :&lt;br /&gt;
&lt;code&gt;[{ &#034;role&#034;: &#034;user&#034;, &#034;content&#034;: &#034;...&#034; }, ...]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nettoie et &lt;strong&gt;compresse&lt;/strong&gt; l'historique pour compatibilit&#233; ReAct,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;stocke :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;self.conversation_history&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;self.compressed_history&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L'agent est &lt;strong&gt;statique&lt;/strong&gt; :&lt;br /&gt;
&#8594; l'application appelante doit g&#233;rer la persistance de l'historique ( plus pr&#233;cis&#233;ment &#034;historique de conversation&#034; ) et le transmettre avant chaque requ&#234;te.&lt;/p&gt;
&lt;h2&gt;3.4. Ex&#233;cution asynchrone &#8212; &lt;code&gt;stream(prompt)&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;Fonctionnement&lt;/h3&gt;
&lt;p&gt;Pour chaque prompt :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ToolRouter&lt;/strong&gt; s&#233;lectionne dynamiquement les outils pertinents&lt;br /&gt;
&#8594; r&#233;duction du contexte, optimisation des co&#251;ts, meilleure pr&#233;cision.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;L'agent ReAct est &lt;strong&gt;reconstruit&lt;/strong&gt; avec uniquement les outils rout&#233;s.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Un &lt;strong&gt;tote bag&lt;/strong&gt; est pr&#233;par&#233; :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;historique compress&#233;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;langue&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;profil (ex. &#034;expert&#034;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Le &lt;strong&gt;ReActFinalizer&lt;/strong&gt; g&#232;re la g&#233;n&#233;ration incr&#233;mentale.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La m&#233;thode retourne un &lt;strong&gt;AsyncGenerator&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;3.5. Ex&#233;cution synchrone &#8212; &lt;code&gt;get_engine_response()&lt;/code&gt;&lt;/h2&gt;
&lt;h3&gt;Fonctionnement&lt;/h3&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;r&#233;cup&#232;re l'historique compress&#233; si non fourni,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;applique le ToolRouter,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ex&#233;cute l'agent ReAct,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;retourne une &lt;strong&gt;r&#233;ponse compl&#232;te&lt;/strong&gt; (non stream&#233;e).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;h1&gt;4. Mise en &#339;uvre des outils dans ReActAgent&lt;/h1&gt;
&lt;h2&gt;4.1. Les outils&lt;/h2&gt;
&lt;p&gt;L'agent s'appuie sur trois ToolKits compl&#233;mentaires :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GeneralToolKit&lt;/strong&gt; : outils g&#233;n&#233;riques toujours disponibles.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ThemeToolKit&lt;/strong&gt; : outils m&#233;tier + un &lt;strong&gt;outil RAG&lt;/strong&gt; pour acc&#233;der &#224; la documentation interne.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ToolKit Temps R&#233;el&lt;/strong&gt; : outils connect&#233;s &#224; des sources de donn&#233;es dynamiques (internes/externes).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voir &#233;galement : &lt;a href='https://ia.dnc.global/ReAct-et-integration-des-donnees-temps-reel-avec-MCP.html' class='spip_in'&gt;ReAct et int&#233;gration des donn&#233;es temps r&#233;el avec MCP ( Model Context Protocol ) &lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;4.2. L'outil RAG dans la boucle ReAct&lt;/h2&gt;
&lt;p&gt;Le RAG (Research Augmented Generation) est int&#233;gr&#233; &lt;strong&gt;comme un outil standard&lt;/strong&gt;, accessible via la logique ReAct.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;R&#244;le du RAG&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Il permet &#224; l'agent d'interroger la documentation interne de l'entreprise, compos&#233;e de :
documents historiques (rapports, notes, logs),
r&#233;f&#233;rentiels documentaires (proc&#233;dures, notices techniques),
routines sp&#233;cialis&#233;es pour guider le raisonnement dans des t&#226;ches r&#233;p&#233;titives.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Fonction dans ReAct&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Le RAG est utilis&#233; lorsque l'agent doit :
v&#233;rifier une information interne,
s'appuyer sur des documents de r&#233;f&#233;rence,
ex&#233;cuter une t&#226;che n&#233;cessitant un contexte m&#233;tier document&#233;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Le RAG enrichit le raisonnement de l'agent en lui donnant acc&#232;s &#224; la connaissance interne, tout en restant orchestr&#233; par ReAct.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;4.3. le ToolRouter&lt;/h2&gt;
&lt;p&gt;Le ToolRouter identifie automatiquement les outils les plus adapt&#233;s &#224; une requ&#234;te utilisateur gr&#226;ce &#224; un m&#233;canisme de similarit&#233; vectorielle.&lt;/p&gt;
&lt;p&gt;Fonctionnement :
Chaque outil poss&#232;de une description textuelle (m&#233;tadonn&#233;es). Voir : &lt;a href='https://ia.dnc.global/ReAct-l-Intent-Map.html' class='spip_in'&gt;ReAct : la carte des intentions : Intent Map&lt;/a&gt;
Les descriptions et la requ&#234;te utilisateur sont vectoris&#233;es via un mod&#232;le d'embedding.
Le routeur calcule la similarit&#233; cosinus entre la requ&#234;te et chaque outil.
Les outils sont class&#233;s par pertinence.
Le ReActAgent choisit l'outil &#224; appeler en fonction du classement et du contexte.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;R&#233;sultat : Un agent capable de combiner raisonnement, outils sp&#233;cialis&#233;s, documentation interne et donn&#233;es temps r&#233;el.&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>



</channel>

</rss>
