
monty v0.0.20
Un interpréteur Python minimal et sécurisé écrit en Rust pour utilisation par l'IA.
Monty
Un interpréteur Python minimal et sécurisé écrit en Rust pour être utilisé par l'IA.
Expérimental - Ce projet est encore en développement et n'est pas prêt pour une utilisation en production.
Un interpréteur Python minimal et sécurisé écrit en Rust pour être utilisé par l'IA.
Monty évite le coût, la latence, la complexité et les tracas d'un sandbox complet basé sur des conteneurs pour exécuter du code généré par un LLM.
Au lieu de cela, il vous permet d'exécuter en toute sécurité du code Python écrit par un LLM intégré à votre agent, avec des temps de démarrage mesurés en microsecondes à un chiffre, et non en centaines de millisecondes.
Ce que Monty peut faire :
- Exécuter un sous-ensemble raisonnable de code Python - suffisant pour que votre agent exprime ce qu'il veut faire
- Bloquer complètement l'accès à l'environnement hôte : le système de fichiers, les variables d'environnement et l'accès réseau sont tous implémentés via des appels de fonctions externes que le développeur peut contrôler
- Appeler des fonctions sur l'hôte - uniquement les fonctions auxquelles vous lui donnez accès
- Exécuter la vérification de types - monty prend en charge les annotations de types Python modernes complètes et est fourni avec ty inclus dans un seul binaire pour exécuter la vérification de types
- Être instantanément sérialisé en octets lors des appels de fonctions externes, ce qui signifie que vous pouvez stocker l'état de l'interpréteur dans un fichier ou une base de données, et reprendre plus tard
- Démarrer extrêmement rapidement (<1μs entre le code et le résultat d'exécution), et avoir des performances d'exécution similaires à celles de CPython (généralement entre 5 fois plus rapides et 5 fois plus lentes)
- Être appelé depuis Rust, Python ou Javascript - parce que Monty n'a aucune dépendance à CPython, vous pouvez l'utiliser partout où vous pouvez exécuter du Rust
- Contrôler l'utilisation des ressources - Monty peut suivre l'utilisation de la mémoire, la profondeur de la pile et le temps d'exécution, et annuler l'exécution si elle dépasse les limites prédéfinies
- Collecter stdout et stderr et les renvoyer à l'appelant
- Exécuter du code asynchrone ou synchrone sur l'hôte via du code asynchrone ou synchrone sur l'hôte
- Utiliser un petit sous-ensemble de la bibliothèque standard :
sys,os,typing,asyncio,re,datetime,json,dataclasses(bientôt)
Ce que Monty ne peut pas faire :
- Utiliser le reste de la bibliothèque standard
- Utiliser des bibliothèques tierces (comme Pydantic) ; la prise en charge de bibliothèques Python externes n'est pas un objectif
- définir des classes (la prise en charge devrait arriver bientôt)
- utiliser les instructions match (encore une fois, la prise en charge devrait arriver bientôt)
En bref, Monty est extrêmement limité et conçu pour un seul cas d'usage :
Exécuter du code écrit par des agents.
Pour comprendre pourquoi vous pourriez vouloir faire cela, consultez :
- Codemode de Cloudflare
- Appel d'outil programmatique d'Anthropic
- Exécution de code avec MCP d'Anthropic
- Smol Agents de Hugging Face
En termes très simples, l'idée de tout ce qui précède est que les LLM peuvent travailler plus vite, à moindre coût et de manière plus fiable si on leur demande d'écrire du code Python (ou Javascript) au lieu de s'appuyer sur l'appel d'outils traditionnel. Monty rend cela possible sans la complexité d'un sandbox ni le risque d'exécuter du code directement sur l'hôte.
Remarque : Monty sera (bientôt) utilisé pour implémenter codemode dans Pydantic AI
Utilisation
Monty peut être appelé depuis Python, JavaScript/TypeScript ou Rust.
Python
Pour installer :```bash uv add pydantic-monty
(Ou `pip install pydantic-monty` pour les boomers)
`pydantic-monty` est un méta-paquet associant `pydantic-monty-client` (le module `pydantic_monty`) avec `pydantic-monty-runtime` (le binaire worker `monty`). Installez `pydantic-monty-client` seul si le binaire provient déjà d'ailleurs.
Utilisation :```python
from typing import Any
import pydantic_monty
code = """
async def agent(prompt: str, messages: Messages):
while True:
print(f'messages so far: {messages}')
output = await call_llm(prompt, messages)
if isinstance(output, str):
return output
messages.extend(output)
await agent(prompt, [])
"""
type_definitions = """
from typing import Any
Messages = list[dict[str, Any]]
async def call_llm(prompt: str, messages: Messages) -> str | Messages:
raise NotImplementedError()
prompt: str = ''
"""
Messages = list[dict[str, Any]]
async def call_llm(prompt: str, messages: Messages) -> str | Messages:
if len(messages) < 2:
return [{'role': 'system', 'content': 'example response'}]
else:
return f'example output, message count {len(messages)}'
async def main():
async with pydantic_monty.AsyncMonty() as pool:
async with pool.checkout(
script_name='agent.py',
type_check=True,
type_check_stubs=type_definitions,
) as session:
output = await session.feed_run(
code,
inputs={'prompt': 'testing'},
external_lookup={'call_llm': call_llm},
)
print(output)
#> example output, message count 2
if __name__ == '__main__':
import asyncio
asyncio.run(main())
L'exécution a lieu dans un pool de sous-processus de travail monty, donc même une erreur mémoire
déclenchée par du code hostile (débordement de pile, arrêt de l'allocateur) ne peut
jamais faire planter votre processus — le travailleur meurt, lève MontyCrashedError, et
est remplacé. Il existe également une API entièrement synchrone :```python
import pydantic_monty
with pydantic_monty.Monty() as pool: with pool.checkout() as session: # session state persists between feed_run calls session.feed_run('x = 21') print(session.feed_run('x * 2')) #> 42
### JavaScript / TypeScript