
Un interpréteur Python minimal et sécurisé écrit en Rust pour utilisation 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 :
sys, os, typing, asyncio, re, datetime, json, dataclasses (bientôt)Ce que Monty ne peut pas faire :
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 :
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
Monty peut être appelé depuis Python, JavaScript/TypeScript ou Rust.
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