Обновить

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 тестов пройдены):

  1. MoMo Payment API v4: 3-way ветвление, HMAC-SHA256 IPN верификация, цикл пуллинга статуса с ретраями.

  2. 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 для распределенного трассирования шагов.

Репозитории проекта:

Теги:
-1
Комментарии0

Публикации