Fournisseurs : une implémentation par protocole — explication
De quoi s'agit-il ?
mm dialogue avec un serveur de modèle local via l'API chat-completions d'OpenAI. Deux serveurs sont pris en charge d'origine, Docker Model Runner et llama-server de llama.cpp, sous les noms dmr et llamacpp. Le paquet moteur était autrefois lié à Docker Model Runner ; l'abstraction de fournisseur est ce qui l'a généralisé.
Pourquoi c'est conçu ainsi
Un type de fournisseur par protocole réseau, pas par éditeur. Quand le moteur a été extrait, exactement une fonction et deux constantes de chaîne étaient spécifiques à Docker Model Runner. Tout le reste, le streaming, le watchdog, la nouvelle tentative, le compteur de commandes, se comportait de la même façon face à un faux moteur qui n'est pas DMR non plus. Donc dmr et llamacpp sont deux entrées de données d'un seul type openaiCompat : une URL de base par défaut, une URL de repli optionnelle, une politique de clé, et les mots employés dans les messages d'erreur. Ajouter un autre serveur compatible OpenAI est une entrée de registre ; ajouter un protocole différent serait un nouveau type.
Un fournisseur possède quatre choses. Il résout la configuration en un backend concret (URL après surcharges d'environnement et sonde de repli, clé lue dans l'environnement, nom du modèle) ; il ouvre Genkit avec son plugin ; il sonde le serveur avant la première question ; et il explique une erreur de transport en une ligne.
Le repli existe pour les conteneurs. Sur l'hôte, Docker Model Runner écoute sur localhost:12434 ; depuis un conteneur ou une sandbox, le même serveur est joignable en host.docker.internal. Si l'URL principale ne répond pas sur /models en deux secondes, le repli est utilisé. Une surcharge explicite par l'environnement saute la sonde : qui l'a posée sait où est le serveur. Un fallback: "" explicite le désactive, ce dont une configuration de test a besoin pour rester épinglée à une seule URL.
La clé ne va jamais dans le YAML. Le fichier nomme la variable d'environnement qui contient la clé, ce qui permet de le committer et de le montrer à l'écran. Les serveurs qui ignorent l'en-tête reçoivent une valeur factice, parce que le client OpenAI veut quelque chose à cet endroit. Un 401 est alors expliqué en nommant la variable que le fournisseur a réellement lue, ou, quand aucune n'est configurée, en pointant l'URL.
La sonde est un conseil, jamais un échec. Sur une machine de démo, le serveur est souvent démarré après l'agent. La sonde vérifie la joignabilité, avertit quand le modèle configuré n'est pas dans la liste de DMR, et sur llama.cpp lit la taille de contexte servie sur /props, un niveau au-dessus de /v1, parce que ce point d'accès rapporte ce que le serveur sert, pas ce sur quoi le modèle a été entraîné. Quand la fenêtre est encore inconnue et que la compression est activée, le REPL sonde à nouveau avant la première question.
Les erreurs sont réécrites dans les mots du serveur. Une pile de messages imbriqués est du bruit ; « tool calls need llama-server started with --jinja » est tout le diagnostic. Le fournisseur reconnaît les refus de connexion, l'option --jinja manquante, les 401/403, les 404 avec une indication de pull ou d'alias, les 429 et les 5xx. Les erreurs inconnues reviennent inchangées : un message brut vaut mieux qu'une mauvaise piste.
Alternatives écartées
- Un fournisseur par éditeur avec du code moteur dupliqué. Écarté : mesurée, la partie spécifique à l'éditeur tenait en trois identifiants.
- Mettre la clé d'API dans le fichier de configuration. Écarté parce que le fichier est fait pour être committé et montré.
- Échouer au démarrage quand le serveur est arrêté. Écarté parce que démarrer le serveur en second est la situation normale d'une démo.
Liens avec le reste
- Les deux fichiers de configuration qui paramètrent chaque fournisseur sont listés dans la référence de la configuration.
- La fenêtre apprise par la sonde est ce contre quoi la compression du contexte mesure.
- Changer de serveur pour une exécution est couvert dans comment faire tourner sur llama.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|