<?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=13&amp;page=backend" rel="self" type="application/rss+xml" />




<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>Chargement des index</title>
		<link>https://ia.dnc.global/Chargement-des-index.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Chargement-des-index.html</guid>
		<dc:date>2026-06-25T06:58:00Z</dc:date>
		<dc:format>text/html</dc:format>
		<dc:language>fr</dc:language>
		<dc:creator>Bertrand Degoy</dc:creator>



		<description>
&lt;p&gt;Le chargement des index repose sur une architecture modulaire o&#249; chaque composant joue un r&#244;le pr&#233;cis, depuis le daemon initial jusqu'aux services distants qui exploitent les donn&#233;es en RAM.
&lt;br class='autobr' /&gt;
L'objectif est de garantir un chargement efficace, unifi&#233; et non redondant des index, tout en permettant une mise en m&#233;moire centralis&#233;e et partag&#233;e.
&lt;br class='autobr' /&gt;
Gr&#226;ce au ThemeIndexLoaderManager, les index sont reconstruits depuis le disque via des loaders sp&#233;cialis&#233;s, normalis&#233;s en backends homog&#232;nes, puis mis &#224; disposition (...)&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;Le chargement des index repose sur une architecture modulaire o&#249; chaque composant joue un r&#244;le pr&#233;cis, depuis le daemon initial jusqu'aux services distants qui exploitent les donn&#233;es en RAM.&lt;br class='autobr' /&gt;
L'objectif est de garantir un chargement efficace, unifi&#233; et non redondant des index, tout en permettant une mise en m&#233;moire centralis&#233;e et partag&#233;e.&lt;br class='autobr' /&gt;
Gr&#226;ce au ThemeIndexLoaderManager, les index sont reconstruits depuis le disque via des loaders sp&#233;cialis&#233;s, normalis&#233;s en backends homog&#232;nes, puis mis &#224; disposition des services Pyro5 pour r&#233;pondre aux requ&#234;tes des clients. L'ensemble forme une cha&#238;ne coh&#233;rente, optimis&#233;e pour la performance et la r&#233;utilisation.&lt;/p&gt;&lt;/div&gt;
		&lt;hr /&gt;
		&lt;div &lt;div class='rss_ps'&gt;&lt;hr /&gt;
&lt;h1&gt;Chargement des index&lt;/h1&gt;
&lt;h2&gt;Architecture g&#233;n&#233;rale&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;daemon.py &#8595;
MemoryManager &#8595;
IndexServer &#8595;
RemoteIndexService (cr&#233;&#233;s &#224; la demande) &#8595;
ThemeIndexLoaderManager (loader) &#8595;
Index en RAM&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Description des composants&lt;/h2&gt;
&lt;h3&gt;daemon.py&lt;/h3&gt;
&lt;p&gt;Point d'entr&#233;e du syst&#232;me. Initialise :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;MemoryManager (gestion centralis&#233;e de la RAM)&lt;/li&gt;
&lt;li&gt;IndexServer (service ma&#238;tre des index)&lt;/li&gt;
&lt;li&gt;ThemeIndexLoaderManager (factory de loaders)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il enregistre les services Pyro5 et expose IndexServer.&lt;/p&gt;
&lt;h3&gt;MemoryManager&lt;/h3&gt;
&lt;p&gt;Gestionnaire RAM partag&#233;.&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Stocke les backends d'index en m&#233;moire &lt;/li&gt;
&lt;li&gt;Applique les politiques LRU/MRU &lt;/li&gt;
&lt;li&gt;Fournit &lt;code&gt;get()&lt;/code&gt;, &lt;code&gt;set()&lt;/code&gt;, &lt;code&gt;touch()&lt;/code&gt; pour la gestion des index &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;IndexServer&lt;/h3&gt;
&lt;p&gt;Service ma&#238;tre Pyro5.&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Centralise le chargement des index &lt;/li&gt;
&lt;li&gt;Un seul backend par th&#232;me &lt;/li&gt;
&lt;li&gt;Cr&#233;e les RemoteIndexService &#224; la demande &lt;/li&gt;
&lt;li&gt;R&#233;utilise les services d&#233;j&#224; cr&#233;&#233;s &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IndexServer &lt;strong&gt;ne charge jamais directement depuis le disque&lt;/strong&gt; : il d&#233;l&#232;gue au ThemeIndexLoaderManager.&lt;/p&gt;
&lt;h3&gt;RemoteIndexService&lt;/h3&gt;
&lt;p&gt;Service Pyro5 par th&#232;me.&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Re&#231;oit les requ&#234;tes du client &lt;/li&gt;
&lt;li&gt;Ex&#233;cute les op&#233;rations sur l'index en RAM &lt;/li&gt;
&lt;li&gt;Ne charge jamais lui-m&#234;me un index : il d&#233;pend d'IndexServer &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ThemeIndexLoaderManager (IndexLoaderFactory)&lt;/h3&gt;
&lt;p&gt;Factory de loaders.&lt;br /&gt;
Responsable de &lt;strong&gt;toute la cha&#238;ne de chargement depuis le disque&lt;/strong&gt; :&lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;Lire la configuration du th&#232;me &lt;/li&gt;
&lt;li&gt;D&#233;terminer le type d'index &#224; charger &lt;/li&gt;
&lt;li&gt;Instancier le loader concret &lt;/li&gt;
&lt;li&gt;Charger les donn&#233;es persist&#233;es depuis le disque &lt;/li&gt;
&lt;li&gt;Construire un backend unifi&#233; &lt;/li&gt;
&lt;li&gt;Retourner le backend &#224; IndexServer &lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;Cha&#238;ne de chargement des index depuis le disque&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;(d&#233;taill&#233;e depuis IndexLoaderFactory / ThemeIndexLoaderManager)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;1. Vue d'ensemble du pipeline&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;IndexLoaderFactory (ThemeIndexLoaderManager) &#8595;
S&#233;lection du loader (selon th&#232;me + config) &#8595;
Loader concret (LlamaIndexLoader, FAISSLoader, etc.) &#8595;
Chargement depuis le disque &#8595;
Construction du backend unifi&#233; &#8595;
Retour &#224; IndexServer &#8595;
Stockage dans MemoryManager (RAM) &#8595;
RemoteIndexService utilise l'index&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2. IndexLoaderFactory / ThemeIndexLoaderManager&lt;/h2&gt;
&lt;p&gt;Ce composant est &lt;strong&gt;la factory centrale&lt;/strong&gt;.&lt;br /&gt;
Il est responsable de :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Lire la configuration du th&#232;me (ex : &lt;code&gt;theme_config.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;D&#233;terminer le &lt;strong&gt;type d'index&lt;/strong&gt; &#224; charger :&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;llama_index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;faiss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dummy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;custom&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Instancier &lt;strong&gt;le loader concret&lt;/strong&gt; correspondant&lt;/li&gt;
&lt;li&gt;Appeler &lt;code&gt;loader.load()&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Retourner un &lt;strong&gt;backend unifi&#233;&lt;/strong&gt;, pr&#234;t &#224; &#234;tre mis en RAM&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;R&#244;le cl&#233;&lt;/h3&gt;
&lt;p&gt;Il garantit que &lt;strong&gt;IndexServer ne conna&#238;t jamais les loaders concrets&lt;/strong&gt;.&lt;br /&gt;
IndexServer ne manipule que des &lt;em&gt;backends unifi&#233;s&lt;/em&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. S&#233;lection du loader&lt;/h2&gt;
&lt;p&gt;La factory applique une logique typique :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;index_type = theme_config.get(&#034;index_type&#034;, &#034;llama_index&#034;) if index_type == &#034;llama_index&#034;: loader = LlamaIndexLoader(theme_name, theme_config)
elif index_type == &#034;faiss&#034;: loader = FAISSLoader(theme_name, theme_config)
else: loader = DummyLoader(theme_name)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Chaque loader :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;conna&#238;t son r&#233;pertoire de stockage&lt;/li&gt;
&lt;li&gt;conna&#238;t son format de donn&#233;es&lt;/li&gt;
&lt;li&gt;sait reconstruire un backend utilisable&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. Loader concret : chargement depuis le disque&lt;/h2&gt;
&lt;h3&gt;Exemple : LlamaIndexLoader&lt;/h3&gt;
&lt;p&gt;Responsable de :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Construire un &lt;code&gt;StorageContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Charger les fichiers persist&#233;s :&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;docstore.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vector_store.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;index_store.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Recr&#233;er l'index LlamaIndex complet&lt;/li&gt;
&lt;li&gt;Appliquer le mod&#232;le d'embedding (si n&#233;cessaire)&lt;/li&gt;
&lt;li&gt;Retourner un objet Python opaque (backend)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pseudo-code :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;def load(self): storage = StorageContext.from_defaults(persist_dir=self.storage_dir) index = load_index_from_storage(storage) return index&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Exemple : FAISSLoader&lt;/h3&gt;
&lt;p&gt;Responsable de :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Charger le fichier &lt;code&gt;.faiss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Charger les m&#233;tadonn&#233;es associ&#233;es&lt;/li&gt;
&lt;li&gt;Recr&#233;er l'index FAISS en RAM&lt;/li&gt;
&lt;li&gt;Retourner un backend unifi&#233;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pseudo-code :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;def load(self): faiss_index = faiss.read_index(self.index_path) metadata = json.load(open(self.meta_path)) return FAISSBackend(faiss_index, metadata)&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;DummyLoader&lt;/h3&gt;
&lt;p&gt;Toujours utile pour les tests :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;def load(self): return {&#034;theme&#034;: self.theme_name, &#034;data&#034;: &#034;fake_index&#034;}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5. Construction du backend unifi&#233;&lt;/h2&gt;
&lt;p&gt;Chaque loader retourne un objet diff&#233;rent :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;LlamaIndex &#8594; &lt;code&gt;VectorStoreIndex&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;FAISS &#8594; &lt;code&gt;FAISSBackend&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Dummy &#8594; dict&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La factory applique ensuite une &lt;strong&gt;normalisation&lt;/strong&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;backend = IndexBackend(index_object, index_type)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce backend :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;expose une API homog&#232;ne (&lt;code&gt;query()&lt;/code&gt;, &lt;code&gt;search()&lt;/code&gt;, &lt;code&gt;metadata()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;masque les diff&#233;rences entre loaders&lt;/li&gt;
&lt;li&gt;permet &#224; RemoteIndexService d'&#234;tre totalement g&#233;n&#233;rique&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6. Retour &#224; IndexServer&lt;/h2&gt;
&lt;p&gt;IndexServer re&#231;oit le backend :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;backend = loader_manager.load(theme_name)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Puis :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;stocke le backend dans MemoryManager&lt;/li&gt;
&lt;li&gt;cr&#233;e un RemoteIndexService si n&#233;cessaire&lt;/li&gt;
&lt;li&gt;retourne le backend ou le service au daemon&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IndexServer &lt;strong&gt;ne recharge jamais&lt;/strong&gt; un index d&#233;j&#224; en RAM.&lt;/p&gt;
&lt;h2&gt;7. Stockage dans MemoryManager (RAM)&lt;/h2&gt;
&lt;p&gt;MemoryManager :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;stocke le backend sous la cl&#233; &lt;code&gt;theme_name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;applique une politique LRU/MRU&lt;/li&gt;
&lt;li&gt;garantit qu'un index n'est charg&#233; &lt;strong&gt;qu'une seule fois&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La politique LRU/MRU (Least Recently Used / Most Recently Used) est un m&#233;canisme de gestion de la m&#233;moire qui permet de d&#233;cider quel objet doit &#234;tre &#233;vinc&#233; lorsque la RAM atteint sa capacit&#233; maximale. Elle repose sur un principe simple :
MRU = objets r&#233;cemment utilis&#233;s &#8594; &#224; conserver
LRU = objets peu utilis&#233;s r&#233;cemment &#8594; candidats &#224; l'&#233;viction&lt;/p&gt;
&lt;p&gt;Cette politique est appliqu&#233;e par le MemoryManager, qui maintient un ordre strict des objets en RAM gr&#226;ce &#224; un OrderedDict.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-python&#034;&gt;memory.set(theme_name, backend)&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8. Utilisation par RemoteIndexService&lt;/h2&gt;
&lt;p&gt;RemoteIndexService :&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;r&#233;cup&#232;re l'index en RAM via MemoryManager&lt;/li&gt;
&lt;li&gt;ex&#233;cute les requ&#234;tes :&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;search()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;query()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;similarity()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ne charge jamais lui-m&#234;me un index&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;R&#233;sum&#233; du chargement depuis le disque&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&#201;tape&lt;/th&gt;
&lt;th&gt;Composant&lt;/th&gt;
&lt;th&gt;R&#244;le&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;IndexLoaderFactory&lt;/td&gt;
&lt;td&gt;Choix du loader + orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Loader concret&lt;/td&gt;
&lt;td&gt;Lecture disque + reconstruction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Factory&lt;/td&gt;
&lt;td&gt;Normalisation backend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;IndexServer&lt;/td&gt;
&lt;td&gt;Stockage + exposition Pyro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;MemoryManager&lt;/td&gt;
&lt;td&gt;Mise en RAM + LRU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;RemoteIndexService&lt;/td&gt;
&lt;td&gt;Utilisation de l'index&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
		
		</content:encoded>


		

	</item>
<item xml:lang="fr">
		<title>Trois modes de chargement des mod&#232;les</title>
		<link>https://ia.dnc.global/Trois-modes-de-chargement-des-modeles.html</link>
		<guid isPermaLink="true">https://ia.dnc.global/Trois-modes-de-chargement-des-modeles.html</guid>
		<dc:date>2026-06-24T09:23:00Z</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 v200, les mod&#232;les peuvent &#234;tre charg&#233;s de trois mani&#232;res : via une API distante (comme Mistral), en local sans persistance (chargement HuggingFace classique dans le process), ou en m&#233;moire persistante gr&#226;ce &#224; un service Pyro5. &lt;br class='autobr' /&gt;
Les deux premiers modes sont simples mais limit&#233;s : l'API impose une latence r&#233;seau et des co&#251;ts, tandis que le chargement local dispara&#238;t d&#232;s que le process se termine. &lt;br class='autobr' /&gt;
Pyro5 apporte une troisi&#232;me voie : un daemon Python ind&#233;pendant, capable de conserver des (...)&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 v200, les mod&#232;les peuvent &#234;tre charg&#233;s de trois mani&#232;res : via une API distante (comme Mistral), en local sans persistance (chargement HuggingFace classique dans le process), ou en m&#233;moire persistante gr&#226;ce &#224; un service Pyro5.&lt;/p&gt;
&lt;p&gt;Les deux premiers modes sont simples mais limit&#233;s : l'API impose une latence r&#233;seau et des co&#251;ts, tandis que le chargement local dispara&#238;t d&#232;s que le process se termine.&lt;/p&gt;
&lt;p&gt;Pyro5 apporte une troisi&#232;me voie : un daemon Python ind&#233;pendant, capable de conserver des objets lourds (embedding, index, SLM) en RAM de mani&#232;re durable, et de les exposer via RPC &#224; tous les composants du runtime.&lt;/p&gt;
&lt;p&gt;Dans ce mod&#232;le, models.json d&#233;crit les mod&#232;les &#224; charger, ModelsConfigurator les instancie une seule fois au d&#233;marrage, puis AppSettings les expose &#224; l'ensemble du syst&#232;me.&lt;/p&gt;
&lt;p&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 (embedding, SLM, indexation, m&#233;moire) en s'appuyant sur les objets d&#233;j&#224; initialis&#233;s, garantissant ainsi coh&#233;rence, performance et s&#233;paration stricte 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;Introduction&lt;/h1&gt;
&lt;p&gt;Dans l'architecture v200, la gestion des mod&#232;les repose sur une s&#233;paration stricte entre trois modes de chargement : &lt;/p&gt;
&lt;ol class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;strong&gt;API distante&lt;/strong&gt; (ex. Mistral) &#8212; aucun co&#251;t m&#233;moire local, mais latence r&#233;seau et d&#233;pendance externe. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chargement local non persistant&lt;/strong&gt; &#8212; les mod&#232;les HF sont charg&#233;s dans le process courant, mais disparaissent d&#232;s que le process se termine. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chargement persistant via Pyro5&lt;/strong&gt; &#8212; un daemon Python ind&#233;pendant conserve les mod&#232;les lourds en RAM et expose leurs capacit&#233;s via RPC, permettant une mutualisation entre plusieurs composants du runtime.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cette architecture permet d'adapter le chargement des mod&#232;les aux contraintes mat&#233;rielles (CPU, GPU, RAM), tout en garantissant une coh&#233;rence stricte : &lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;&lt;code&gt;models.json&lt;/code&gt; d&#233;crit les mod&#232;les &#224; charger. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;ModelsConfigurator&lt;/code&gt; les instancie une seule fois. &lt;/li&gt;
&lt;li&gt;&lt;code&gt;AppSettings&lt;/code&gt; les stocke en m&#233;moire. &lt;/li&gt;
&lt;li&gt;Les services Pyro5 les consomment via RPC sans jamais les recharger.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Vue d'ensemble du pipeline v200&lt;/h1&gt;
&lt;p&gt;&lt;span class='spip_document_50 spip_documents spip_documents_center'&gt;
&lt;img src='https://ia.dnc.global/IMG/png/modelsconfigurator_workflow-2026-06-28-090730.png' width=&#034;1783&#034; height=&#034;6185&#034; alt=&#034;&#034; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;1. Les trois modes de chargement des mod&#232;les&lt;/h1&gt;
&lt;h2&gt;1.1 Mod&#232;les API (ex. Mistral)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Caract&#233;ristiques :&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Aucun co&#251;t m&#233;moire local &lt;/li&gt;
&lt;li&gt;Latence r&#233;seau &lt;/li&gt;
&lt;li&gt;D&#233;pendance &#224; un fournisseur &lt;/li&gt;
&lt;li&gt;Co&#251;t financier potentiel &lt;/li&gt;
&lt;li&gt;Pas de GPU requis &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Exemple dans &lt;code&gt;models.json&lt;/code&gt; :&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;&#034;llm&#034;: { &#034;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;backend&#034;: &#034;mistral_api&#034;, &#034;api_key&#034;: &#034;env:MISTRAL_API_KEY&#034;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Quand utiliser ?&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Pas de GPU disponible &lt;/li&gt;
&lt;li&gt;RAM limit&#233;e &lt;/li&gt;
&lt;li&gt;Besoin d'un mod&#232;le puissant (Mixtral, Mistral Large) &lt;/li&gt;
&lt;li&gt;D&#233;ploiement cloud ou edge l&#233;ger &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1.2 Mod&#232;les locaux non persistants (HF dans le process)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Caract&#233;ristiques :&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Charg&#233;s par HuggingFace dans le process courant &lt;/li&gt;
&lt;li&gt;Disparaissent &#224; la fin du process &lt;/li&gt;
&lt;li&gt;Temps de chargement non n&#233;gligeable &lt;/li&gt;
&lt;li&gt;N&#233;cessitent RAM + CPU/GPU &lt;/li&gt;
&lt;li&gt;Id&#233;al pour tests, scripts, outils CLI &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Exemple :&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;&#034;slm&#034;: { &#034;model_name&#034;: &#034;TinyLlama/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;model_path&#034;: &#034;/home/user/.models/TinyLlama&#034;, &#034;backend&#034;: &#034;hf&#034;, &#034;device&#034;: &#034;cpu&#034;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Quand utiliser ?&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;D&#233;veloppement local &lt;/li&gt;
&lt;li&gt;Tests unitaires &lt;/li&gt;
&lt;li&gt;Mod&#232;les l&#233;gers (&lt;2&#8239;GB) &lt;/li&gt;
&lt;li&gt;Pas besoin de persistance &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sur ce dernier point, notons qu'un service HTTP Rest ne chargera les mod&#232;les qu'une fois &#224; son lancement ; dans cette configuration, on pourra s'accommoder de la non-persistance, au prix d'un d&#233;lai au re-lancement du service.&lt;/p&gt;
&lt;h2&gt;1.3 Mod&#232;les persistants via Pyro5 (daemon)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Caract&#233;ristiques :&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Mod&#232;les charg&#233;s une seule fois dans un daemon &lt;/li&gt;
&lt;li&gt;Persistants en RAM &lt;/li&gt;
&lt;li&gt;Accessibles via RPC &lt;/li&gt;
&lt;li&gt;Mutualis&#233;s entre plusieurs composants &lt;/li&gt;
&lt;li&gt;Id&#233;al pour embeddings, index, SLM &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Exemple dans &lt;code&gt;services.json&lt;/code&gt; :&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#034;name&#034;: &#034;embedding.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.embedding.embedding_server.EmbeddingServer&#034;, &#034;params&#034;: {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Quand utiliser ?&lt;/strong&gt;&lt;/p&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Mod&#232;les lourds (embedding, SLM) &lt;/li&gt;
&lt;li&gt;Besoin de persistance &lt;/li&gt;
&lt;li&gt;Plusieurs clients doivent acc&#233;der au m&#234;me mod&#232;le &lt;/li&gt;
&lt;li&gt;RAM suffisante (8&#8211;32&#8239;GB selon mod&#232;les) &lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;2. Quelle solution pour quel mod&#232;le ? (selon contraintes mat&#233;rielles)&lt;/h1&gt;
&lt;h2&gt;2.1 Embedding (BGE-small, BGE-large, E5, etc.)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contrainte&lt;/th&gt;
&lt;th&gt;Recommandation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt; 4&#8239;GB RAM&lt;/td&gt;
&lt;td&gt;API ou mod&#232;le tr&#232;s l&#233;ger (BGE-small)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&#8211;8&#8239;GB RAM&lt;/td&gt;
&lt;td&gt;HF local non persistant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&gt; 8&#8239;GB RAM&lt;/td&gt;
&lt;td&gt;Pyro5 persistant (recommand&#233;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pourquoi Pyro5 ?&lt;/strong&gt;&lt;br /&gt;
Les embeddings sont appel&#233;s tr&#232;s souvent &#8594; &#233;viter les rechargements &#8594; gain x10 en latence.&lt;/p&gt;
&lt;h2&gt;2.2 SLM (TinyLlama, Phi-2, Gemma 2B)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contrainte&lt;/th&gt;
&lt;th&gt;Recommandation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU only&lt;/td&gt;
&lt;td&gt;TinyLlama / Phi-2 via Pyro5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU 4&#8211;8&#8239;GB&lt;/td&gt;
&lt;td&gt;Gemma 2B local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU 16&#8239;GB&lt;/td&gt;
&lt;td&gt;Mixtral 8x7B local (rare)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pourquoi Pyro5 ?&lt;/strong&gt;&lt;br /&gt;
Les SLM sont lourds &#224; charger &#8594; persistance indispensable.&lt;/p&gt;
&lt;h2&gt;2.3 Tokenizer&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contrainte&lt;/th&gt;
&lt;th&gt;Recommandation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Toujours&lt;/td&gt;
&lt;td&gt;HF local non persistant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Pourquoi ?&lt;/strong&gt;&lt;br /&gt;
Le tokenizer est l&#233;ger (&lt;200&#8239;MB) &#8594; inutile de le mettre dans Pyro5.&lt;/p&gt;
&lt;h2&gt;2.4 LLM principal (Mistral, Mixtral, Claude, GPT)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contrainte&lt;/th&gt;
&lt;th&gt;Recommandation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pas de GPU&lt;/td&gt;
&lt;td&gt;API obligatoire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU 24&#8211;48&#8239;GB&lt;/td&gt;
&lt;td&gt;Mixtral local possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU &gt; 80&#8239;GB&lt;/td&gt;
&lt;td&gt;Mod&#232;les 70B locaux&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion :&lt;/strong&gt;&lt;br /&gt;
Dans 99&#8239;% des cas &#8594; &lt;strong&gt;API&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;3. Exemples complets&lt;/h1&gt;
&lt;h2&gt;3.1 Exemple &lt;code&gt;models.json&lt;/code&gt; optimis&#233; pour machine CPU 16&#8239;GB&lt;/h2&gt;
&lt;ul class=&#034;spip&#034;&gt;
&lt;li&gt;Embedding en Pyro5 &lt;/li&gt;
&lt;li&gt;SLM en Pyro5 &lt;/li&gt;
&lt;li&gt;Tokenizer local &lt;/li&gt;
&lt;li&gt;LLM via API &lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#034;embedding&#034;: { &#034;model_name&#034;: &#034;BAAI/bge-small-en-v1.5&#034;, &#034;model_path&#034;: &#034;/models/bge-small&#034;, &#034;backend&#034;: &#034;hf&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;slm&#034;: { &#034;model_name&#034;: &#034;TinyLlama/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;model_path&#034;: &#034;/models/tinyllama&#034;, &#034;backend&#034;: &#034;hf&#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;llm&#034;: { &#034;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;backend&#034;: &#034;mistral_api&#034;, &#034;api_key&#034;: &#034;env:MISTRAL_API_KEY&#034; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.2 Exemple &lt;code&gt;services.json&lt;/code&gt; correspondant&lt;/h2&gt;
&lt;p&gt;Voir &lt;a href='https://ia.dnc.global/Construction-des-modeles-models-json-et-services-json.html' class='spip_in'&gt;Construction des mod&#232;les : &lt;code class='spip_code' dir='ltr'&gt;models.json&lt;/code&gt; et &lt;code class='spip_code' dir='ltr'&gt;services.json&lt;/code&gt;&lt;/a&gt;&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;: 50050 }, &#034;services&#034;: [ { &#034;name&#034;: &#034;embedding.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.embedding.embedding_server.EmbeddingServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;slm.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.llm.slm_server.SLMServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;index.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.index.index_server.IndexServer&#034;, &#034;params&#034;: { &#034;embedding_service&#034;: &#034;embedding.server&#034; } }, { &#034;name&#034;: &#034;memory.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.memory_manager.MemoryManager&#034;, &#034;params&#034;: { &#034;embedding_service&#034;: &#034;embedding.server&#034;, &#034;index_service&#034;: &#034;index.server&#034; } } ]
}&lt;/code&gt;&lt;/pre&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&lt;/code&gt; (si backend = API)&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 officielle :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#034;language-json&#034;&gt;{ &#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;hf&#034;, &#034;device&#034;: &#034;cpu&#034; }, &#034;slm&#034;: { &#034;model_name&#034;: &#034;TinyLlama/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;model_path&#034;: &#034;/home/iadnc/.models/TinyLlama-1.1B-Chat-v1.0&#034;, &#034;backend&#034;: &#034;hf&#034;, &#034;device&#034;: &#034;cpu&#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;model_name&#034;: &#034;mistral-medium-latest&#034;, &#034;backend&#034;: &#034;mistral_api&#034;, &#034;api_key&#034;: &#034;env:MISTRAL_API_KEY&#034;, &#034;model_path&#034;: null, &#034;device&#034;: null }
}&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 correcte, 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;: 50050 }, &#034;services&#034;: [ { &#034;name&#034;: &#034;embedding.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.embedding.embedding_server.EmbeddingServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;slm.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.llm.slm_server.SLMServer&#034;, &#034;params&#034;: {} }, { &#034;name&#034;: &#034;index.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.index.index_server.IndexServer&#034;, &#034;params&#034;: { &#034;embedding_service&#034;: &#034;embedding.server&#034; } }, { &#034;name&#034;: &#034;memory.server&#034;, &#034;class&#034;: &#034;runtime_v2.services.memory_manager.MemoryManager&#034;, &#034;params&#034;: { &#034;embedding_service&#034;: &#034;embedding.server&#034;, &#034;index_service&#034;: &#034;index.server&#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>



</channel>

</rss>
