Modèle / jeu de données
jackmpcollins/magentic avatar
jackmpcollins/magentic

magentic : des fonctions Python dont le corps est un appel LLM

Seamlessly integrate LLMs as Python functions

2 425 étoiles127 forksPythonMIT

En bref

De quoi s’agit-il ?
La bibliothèque magentic transforme une signature de fonction typée en requête adressée à un modèle, et renvoie un objet pydantic. Le mécanisme est simple à comprendre, mais il faut accepter que la sortie du modèle devienne une dépendance d'exécution.
À qui s’adresse-t-il ?
Adoptez magentic si vous écrivez déjà du Python typé et voulez que le schéma pydantic serve de contrat avec le modèle, sans construire de couche d'orchestration. Évitez-le si votre application dépend d'appels d'outils en parallèle avec un état partagé entre étapes, ou si vous ne pouvez pas tolérer qu'une réponse hors schéma fasse échouer la fonction après plusieurs tentatives.
Puis-je l’utiliser commercialement ?
Oui. MIT est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
Est-il encore maintenu ?
L’activité ralentit. Les derniers commits datent d’il y a 6 mois.
En quel langage est-il écrit ?
Principalement Python, d’après les statistiques de langage de GitHub.

Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.

ANALYSE OPEN SOURCE APPROFONDIE

Le problème : une fonction Python dont le corps n'existe pas

Dans le README, la fonction décorée n'a pas de corps. Le commentaire est explicite : « No function body as this is never executed ». La signature fait office de spécification. Le type de retour, `str` ou un modèle pydantic, devient le format attendu de la réponse, et les paramètres deviennent les variables du gabarit. C'est le public visé : quelqu'un qui écrit du Python ordinaire et veut appeler un modèle sans changer de paradigme. Pas de DSL, pas de fichier YAML, pas de graphe de nœuds à déclarer. Une bibliothèque qui impose une structure de graphe vous oblige à réifier des étapes que vous n'auriez peut-être pas isolées autrement. Ici, la fonction reste une fonction, avec ses annotations, et un linter peut la lire.

Du gabarit au modèle pydantic : ce qui circule réellement

Le décorateur `@prompt` prend une chaîne contenant des champs entre accolades, par exemple `'Add more "dude"ness to: {phrase}'`. À l'appel, les arguments sont insérés dans le gabarit, le texte obtenu part vers le fournisseur configuré, et la réponse est convertie vers le type de retour déclaré. Quand ce type est un modèle pydantic, comme la classe `Superhero` du README avec ses champs `name`, `age`, `power` et `enemies`, la conversion devient une validation : le modèle doit produire une structure conforme. `@chatprompt` suit la même logique, mais accepte une séquence de messages (`SystemMessage`, `UserMessage`, `AssistantMessage`) plutôt qu'un texte unique. Le README précise que les champs entre accolades sont remplis dans tous les messages « except FunctionResultMessage ». Ce détail compte : il signifie qu'un exemple de réponse assistant inséré dans le gabarit ne sera pas réécrit au moment de l'appel, ce qui est le comportement attendu pour du few-shot prompting.

FunctionCall et @prompt_chain : deux niveaux d'autonomie distincts

Avec `functions=[search_twitter, search_youtube]`, la fonction décorée peut renvoyer un objet `FunctionCall` au lieu d'une valeur finale. Le README montre la sortie sous la forme `FunctionCall(<function search_twitter at 0x10c367d00>, 'LLMs', 'latest')`, et l'exécution se fait en appelant cet objet. Vous gardez donc la main : le modèle choisit l'outil et les arguments, votre code décide quand l'exécuter. `@prompt_chain` retire cette étape manuelle. La documentation indique qu'il « resolve FunctionCall objects automatically and pass the output back to the LLM to continue until the final answer is reached ». Dans l'exemple météo, le modèle appelle `get_current_weather`, reçoit le résultat, puis formule la réponse finale. La différence entre les deux décorateurs n'est pas cosmétique : elle détermine qui contrôle la boucle. Avec `FunctionCall`, c'est vous. Avec `@prompt_chain`, c'est la bibliothèque, et vous ne voyez pas combien d'allers-retours ont eu lieu sauf via la télémétrie.

Installation et configuration minimale

L'installation tient en une commande, `pip install magentic`, ou `uv add magentic` avec uv. Le README indique de définir la variable d'environnement `OPENAI_API_KEY` pour OpenAI, et renvoie à la page Configuration pour les autres fournisseurs, parmi lesquels Anthropic et Ollama sont cités. Les options de configuration ne sont pas détaillées dans le matériel fourni : je ne peux pas vous dire quels noms de clés utiliser pour changer de fournisseur, seulement que la page existe. Le streaming s'appuie sur `StreamedStr` et `AsyncStreamedStr`, ce qui suppose de traiter la sortie pendant sa génération plutôt qu'après. Pour l'observabilité, le projet s'appuie sur OpenTelemetry avec une intégration Logfire documentée côté Pydantic. Rien dans le README n'indique de fichier de configuration local ni de mécanisme de découverte automatique : la configuration passe par l'environnement et le code.

Les retries assistés par LLM, et ce qu'ils coûtent

Le projet annonce des « LLM-Assisted Retries » pour améliorer l'adhérence du modèle à des schémas de sortie complexes. Le README ne décrit pas l'algorithme, seulement l'existence de la fonctionnalité et un lien vers retrying.md. C'est une limite documentaire réelle : impossible de savoir depuis le matériel fourni combien de tentatives sont faites, si le message d'erreur de validation est renvoyé au modèle, ni si le comportement est configurable. Ce que l'on peut dire, c'est que la fonctionnalité implique des appels supplémentaires au modèle en cas d'échec de validation. Sur un schéma imbriqué et un modèle peu fiable, une fonction qui échoue peut donc coûter plusieurs requêtes avant de lever une exception. C'est le compromis assumé du projet : la validation pydantic est stricte, et la correction est déléguée au modèle plutôt qu'à du code de réparation écrit à la main.

Quand magentic n'est pas le bon outil

Le README mentionne le « Parallel Function Calling » et renvoie à une ancre de la page function-calling. Le matériel fourni ne montre aucun exemple, aucune signature, aucun contrat sur l'ordre des résultats. Si votre cas d'usage dépend de plusieurs outils exécutés simultanément avec un état partagé entre les étapes, c'est précisément l'endroit où la documentation est la plus mince, et vous devrez lire la page avant de vous engager. Autre cas défavorable : une application où l'appel au modèle n'est qu'une ligne dans un pipeline déjà orchestré ailleurs. Ajouter `@prompt` revient à déplacer le contrat vers des annotations Python, ce qui est utile si votre équipe vit dans ce fichier, et inutile si la logique d'orchestration réside dans un service séparé. Enfin, si vous ne pouvez pas accepter qu'une réponse hors schéma fasse échouer la fonction après plusieurs tentatives, le modèle de validation stricte de magentic joue contre vous.

Comparaison avec un accès direct au SDK du fournisseur

L'alternative la plus proche n'est pas un framework concurrent mais le SDK du fournisseur utilisé directement. Avec le SDK, vous construisez le tableau de messages, vous déclarez le schéma JSON vous-même, vous parsez la réponse, et vous gérez les erreurs de validation à la main. La différence d'approche est nette : magentic fait de la signature Python la source du schéma, et délègue la conformité à pydantic plus une couche de retry. Le SDK vous laisse choisir votre propre stratégie de réparation, y compris des solutions déterministes comme une valeur par défaut ou un parsing tolérant. En contrepartie, vous réécrivez cette plomberie pour chaque fonction. Le point de bascule se situe au nombre de fonctions concernées : une ou deux, le SDK suffit ; une dizaine avec des schémas imbriqués et des outils, la couche de validation de magentic commence à compenser son coût.

Licence, maintenance et coût de mise à jour

Le projet est publié sous licence MIT, ce qui autorise la réutilisation, la modification et la redistribution, y compris dans un produit propriétaire, à condition de conserver l'avis de licence. Ce n'est pas un avis juridique : faites relire la notice par qui de droit si vous redistribuez. Côté maintenance, le dépôt n'est pas archivé et la dernière publication, v0.41.1, date du 11 mars 2026, soit le même jour que le dernier push sur la branche main. L'écart entre v0.41.0, publiée en octobre 2025, et v0.41.1, cinq mois plus tard, suggère un rythme de publication irrégulier. Les versions sont encore en 0.x, donc des changements cassants restent possibles entre mineures. Épinglez une version précise dans vos dépendances et lisez les notes de publication avant de monter de v0.40 à v0.41 plutôt que de suivre la branche main.

Conclusion éditoriale

Adoptez magentic si vous écrivez déjà du Python typé et voulez que le schéma pydantic serve de contrat avec le modèle, sans construire de couche d'orchestration. Évitez-le si votre application dépend d'appels d'outils en parallèle avec un état partagé entre étapes, ou si vous ne pouvez pas tolérer qu'une réponse hors schéma fasse échouer la fonction après plusieurs tentatives. Avant de vous engager, lisez la page retrying.md du site et vérifiez la version exacte que vous épinglez, car v0.41.0 et v0.41.1 sont séparées par cinq mois.

Sources officielles

  1. jackmpcollins/magentic on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Notes de la communauté

Notes de la communauté