llm-nano-vm v0.8.0 — выход в PyPI, валидация вывода и per-step таймауты
В прошлом посте мы описывали концепцию nano-vm — детерминированного ядра исполнения на базе конечных автоматов (FSM) для LLM-воркфлоу, где модель не является оркестратором, а лишь предлагает действия внутри жесткого графа \delta(S, E) \to S'.
За это время проект перерос стадию концепта. Мы опубликовали рантайм на PyPI и выпустили релиз v0.8.0. Ниже — сухой отчет о том, что конкретно было сделано, измененено и протестировано.
Что нового в v0.8.0
1. Выход на PyPI и релиз пакетов
Рантайм и сопутствующие компоненты полностью изолированы и доступны для установки:
pip install llm-nano-vm==0.8.0 pip install llm-nano-vm[litellm]==0.8.0 # поддержка провайдеров через LiteLLM pip install nano-vm-mcp # MCP-шлюз
2. allowed_outputs — LLM enum guard
Добавлена жесткая валидация сырого вывода модели по белому списку до того, как значение попадет дальше в пайплайн.
{ "id": "classify", "type": "llm", "prompt": "Classify. Reply ONLY with: refund / query / other", "allowed_outputs": ["refund", "query", "other"], "on_error": "skip", # → подставит "refund" (первый элемент) на mismatch }
Реализовано три политики обработки ошибок: fail (trace \to FAILED), skip (подстановка allowed_outputs[0]) и retry (перезапрос модели до max_retries).
3. timeout_seconds + on_timeout — таймауты на уровне шага
Решена проблема «зависания» внешних LLM API. Любой llm-шаг теперь можно ограничить по времени выполнения с политиками fail или fallback (подстановка дефолтного значения без падения автомата).
4. Стабилизация ASTEngine
Мы окончательно избавились от eval() для условий (condition). Написан кастомный песочный интерпретатор JSON AST. Любые системные вызовы и скрытые вызовы методов (вроде .lower()) теперь вызывают ASTEvalError на этапе компиляции графа.
Результаты бенчмарков (v0.8.0 · WSL2 · Python 3.12)
Тесты производительности на синтетическом адаптере (3 провайдера \times 5 сценариев \times 10k итераций) показали 1,096,500 операций и 0 нарушений контракта графа.
СценарийСредний TPSp95Refund pipeline2,200/s123 msDouble-execution guard2,800/s69 msBudget enforcement2,400/s97 msParallel throughput1,000/s196 msGovernanceEnvelope (аудит-лог)2,100/s108 ms
Crash consistency (BM-INT-07): При
crash_rate=100%повторное воспроизведение (replay) пайплайна после симулированного падения рантайма выдает идентичный хэш трейса в 100% случаев.Memory leak test (BM-INT-10): Пиковый RSS — 76.5 MB, аллокация — 3.62 MB для программ на 1000 шагов. Утечек памяти нет.
Валидация на реальных платежных API
Концепт успешно проверен на двух интеграционных сценариях (9/9 тестов пройдены):
MoMo Payment API v4: 3-way ветвление, HMAC-SHA256 IPN верификация, цикл пуллинга статуса с ретраями.
Stripe Payment API v1: Обработка 3DS-флоу (
REQUIRES_ACTION), refund-пайплайн и верификация вебхуков.
В процессе интеграции со Stripe пофиксили важный баг: коллизию доменного статуса "PENDING" от API Stripe с внутренним сентинелом рантайма, который триггерил заморозку (SUSPEND) автомата.
Текущий фокус и краткосрочный роадмап
Phase 0: Разработка
ProgramValidatorдля статического анализа графов до их выполнения (поиск циклов, недостижимых шагов и битых таргетов). Актуально, когда сами программы генерируются «на лету» внешними моделями.Phase 1: Консистентность шлюза. Перенос
StateContextмежду вызовами MCP в SQLite WAL (execution_contexts+UPSERTна каждый шаг). Это полностью уберет риск повторного списания (Double-Spend) при перезапуске процесса шлюза.Phase 2: Интеграция OpenTelemetry для распределенного трассирования шагов.
Репозитории проекта:
Core runtime: github.com/Ale007XD/nano_vm
MCP layer: github.com/Ale007XD/nano-vm-mcp
