Skip to main content
Glama
gatordevin
by gatordevin

AVO — Agentic Variation Operators

Открытая воспроизводимая реализация AVO: Agentic Variation Operators for Autonomous Evolutionary Search (Chen, Ye, Xu и др., NVIDIA, 2026), запускаемая на ноутбуке.

Классический эволюционный поиск, а также системы с LLM-усилением, которые за ним последовали, раскладывают оператор вариации на фиксированный конвейер:

Vary(P_t) = Generate(Sample(P_t))

Фреймворк выбирает родителей; модель порождает одного кандидата из них. AVO заменяет всю эту декомпозицию одним автономным запуском агента:

Vary(P_t) = Agent(P_t, K, f)

Агент видит всю родословную P_t, базу знаний домена K и функцию оценки f — и сам решает, что читать, что менять и когда измерять. Он перестаёт быть генератором кандидатов и становится оператором вариации.

В этом репозитории реализован этот фреймворк, а также окружающая его механика, описанная в статье: родословная на базе git, вектор оценок с проверкой корректности, политика коммита «совпадает или улучшает», супервизор, вмешивающийся при стагнации, и графики траекторий. В комплекте идут две целевые задачи оптимизации.


Главное: это работает в той сессии, которая у вас уже есть

Драйвер по умолчанию не порождает агента и не вызывает API. Он передаёт промпт вариации сессии Claude Code, с которой вы уже разговариваете, и эта сессия выполняет работу. Ничего дополнительного не списывается, ANTHROPIC_API_KEY не нужен, а агент, выполняющий оптимизацию, — это настоящий универсальный агент для программирования — именно такой, какой использовался в статье.

Автономный режим (порождение агента на каждом шаге и запуск на несколько дней, как в 7-дневном эксперименте из статьи) тоже доступен и включён по желанию именно потому, что расходует квоту.


Related MCP server: Pi-Anvil (pi-sandbox)

Установка

git clone https://github.com/gatordevin/avo
cd avo
pip install -e ".[all]"     # or: pip install -e .  for the core only
avo doctor

В системе с внешне управляемым Python (Homebrew, большинство дистрибутивов Linux) используйте virtualenv — флаг --system-site-packages переиспользует уже имеющиеся NumPy и Matplotlib:

python3 -m venv --system-site-packages .venv
.venv/bin/pip install -e ".[all]"
.venv/bin/avo doctor

Требования: Python 3.10+, git и компилятор C, если нужна цель attention_c. numpy требуется встроенным целям, matplotlib — для графиков. Ядро фреймворка зависит только от PyYAML.


Быстрый старт — управляйте им через уже имеющегося агента

Полный протокол, включая Codex и использование через обычный CLI, — в docs/DRIVING.md.

Claude Code

Зарегистрируйте MCP-сервер один раз, на уровне пользователя, чтобы он был доступен в любой папке:

claude mcp add avo -s user -- python3 -m avo.mcp_server
# from a virtualenv, point at its interpreter:
claude mcp add avo -s user -- /path/to/avo/.venv/bin/python -m avo.mcp_server

claude mcp list должен показать avo — ✔ Connected. При желании установите встроенный навык, чтобы /avo работал где угодно:

cp -r .claude/skills/avo ~/.claude/skills/avo

Затем в сессии Claude Code в любом каталоге:

Используйте инструменты avo, чтобы развивать цель game2048 в течение 10 шагов. Вызовите avo_start_run, затем в цикле: avo_next_step, выполняйте запрошенную работу, avo_evaluate, пока не будете довольны, затем avo_submit. Если он сообщает о застое, вызовите avo_supervisor_brief, ответьте на него и сохраните через avo_record_supervisor.

Одиннадцать инструментов — это весь цикл:

инструмент

что делает

avo_start_run

посев x_0, оценка, замер базовых показателей, открытие родословной

avo_next_step

промпт вариации: P_t, индекс K, контракт для f

avo_evaluate

запуск f на рабочем дереве — бесплатно, вызывайте сколько угодно раз

avo_submit

завершение шага: оценка, затем коммит или откат по политике

avo_revert

отказ от эксперимента без траты шага

avo_status / avo_lineage

где находится запуск

avo_supervisor_brief / avo_record_supervisor

вмешательство при стагнации

avo_plot

отрисовка траектории

avo_list_targets

что можно развивать

Codex

Codex CLI понимает MCP и читает AGENTS.md, так что работают обе части:

codex mcp add avo -- python3 -m avo.mcp_server

AGENTS.md в корне репозитория описывает цикл и правила, которые обеспечивают честность запуска; Codex подхватывает его автоматически при работе в этом каталоге.

Без MCP

У каждого инструмента есть CLI-двойник, так что обычная оболочка работает не хуже — это самый переносимый вариант, подходящий для любого агента или для работы вручную:

avo start --target game2048          # seeds x0 and prints the first prompt
# ... edit runs/<id>/work/, run runs/<id>/avo-eval as often as you like ...
avo submit -m "expectimax depth 2 with a positional weight matrix"
avo prompt                           # the next step's prompt
avo status
avo plot -o trajectory.png

Примеры запусков

В репозитории есть два полных запуска, оба выполнены в сессионном режиме сессией Claude Code, оба включают свои тупики.

attention_decode — превосходим вендорное ядро

examples/attention-decode-run/ развивает шаг декодирования внимания: один токен запроса против длинного KV-кэша — вычисление, которое LLM выполняет для каждого генерируемого токена. Оценка против mx.fast.scaled_dot_product_attention — собственного слитого Metal-ядра Apple.

0.05 → 1.14× MLX за три шага. Это тот случай, когда развитое ядро действительно превосходит вендорную реализацию, и интересно именно как:

  • Шаг 1 был реализацией — flash-decoding с разделением по K подняло ядро с 1.6 ГБ/с до 106 ГБ/с, примерно 95% предела пропускной способности машины. Это достигло 0.95× MLX и исчерпало рычаг: нельзя читать байты быстрее, чем их доставляет контроллер памяти.

  • Шаг 2 был математикой. Порог цели — это бюджет ошибки на выходе, а не точное равенство, поэтому поиск мог изменить вычисление. Измерения показали, что 99.9% массы softmax находится в ~11% ключей, поэтому ядро теперь оценивает каждый ключ, но читает V только выше порога, выбранного так, чтобы отбрасываемая масса была доказуемо меньше 0.3%. Это пересекло 1.0, потратив 2% бюджета ошибки.

Урок обобщается: как только ядро, ограниченное пропускной способностью, достигает потолка производительности, единственный оставшийся рычаг — читать меньше байтов, а это уже алгоритмическое изменение.

Читать полный отчёт →

attention_c — собственная область статьи

examples/attention-c-run/ развивает прямое ядро внимания на C, достигая 2.2× по сравнению с простой реализацией NumPy/BLAS и близко к потолку NEON. Обратите внимание на честную формулировку: этот базовый уровень — не настроенная библиотека внимания, и это ядро медленнее, чем CPU SDPA из torch и MLX — матричные блоки AMX от Apple недостижимы из переносимого C. В отчёте приведено полное сравнение.

Три вывода из него стоят клика:

  • Собственный алгоритм статьи здесь оказался неверным ответом. Черепичное ядро в стиле FlashAttention с потоковым онлайн-softmax показало худший результат дважды. При таких размерах вся голова помещается в L2, так что блокировка для локальности ничего не даёт, а пересчёт масштаба на каждый блок — чистая лишняя работа. Стоимость — арифметика, а не память.

  • -ffast-math молча ломает стандартный быстрый exp, алгебраически сокращая трюк с округлением через добавление магической константы, на котором он основан. Проверка корректности поймала это на форме N=3; показатель пропускной способности никогда бы этого не заметил.

  • Запуск вынудил исправить цель. Оценка сырых ГФЛОП/с на ноутбуке, выполняющем другую работу, — это не измерение: идентичный код давал 44–76 ГФЛОП/с за двадцать минут. eval.py теперь замеряет время NumPy/BLAS-эталона в том же процессе, вперемежку с кандидатом, и оценивает отношение.

Читать полный отчёт →

game2048 — развитие политики для игры

examples/game2048-run/ — это полный запуск из 8 шагов цели game2048, выполненный в сессионном режиме сессией Claude Code. В каталоге хранится неотредактированный вывод: развитая политика, рабочие заметки оператора, полная траектория, созданные им инструменты скрининга и его тупики.

876 → 43 826 — в 50 раз больше посева, в 14 раз сильнее самого сильного базового уровня. Игры, достигающие 2048: 0% → 77%. Лучшая плитка: 512 → 8192. Apple M5, один поток, только стандартная библиотека.

траектория эволюции

Улучшения приходят дискретными скачками, разделёнными плато, что соответствует рисунку 5 из статьи. Две плоские версии — это чисто работа над пропускной способностью, которая купила бюджет, потраченный следующим шагом, — та же роль, что и изменение v19→v20 с безветвевым пересчётом масштаба в статье.

Самый большой единичный прирост (+50.5%) не был оптимизацией. Бенчмарк оценивал накопленные очки игры; эвристика измеряла только то, насколько выживаемо выглядит доска, поэтому ничто в поиске не знало, что слияние двух 256 даёт 512 очков. Четыре шага работы над пропускной способностью дали +27% в сумме; один шаг проверки того, что на самом деле оптимизируется, дал +50%.

Читать полный отчёт →

Что входит в комплект

game2048 — развитие политики для игры

Развивайте agent.py в самого сильного игрока в 2048, какого сможете, при жёстком бюджете времени на размышление. Оценка — геометрическое среднее среднего счёта игры по четырём блокам из двенадцати детерминированных сидов. Превышение бюджета в 120 с даёт ноль, а не «чуть меньше», — поэтому глубина поиска, стоимость функции оценки и отсечения конкурируют друг с другом, и этот компромисс и есть задача.

Измерено на Apple M5:

политика

счёт

посев x_0 (первый легальный ход)

876

случайный базовый уровень

1 076

базовый уровень эвристики угла

2 565

жадный базовый уровень на один ход

3 132

Сильные игроки на expectimax набирают десятки тысяч. Приведённый выше запуск достиг 43 826.

attention_c — развитие ядра, собственная область статьи

Развивайте ядро прямого внимания одинарной точности на C: O = softmax(QKᵀ/√D)V, причинное и непричинное, D = 64. Проверка — согласие с эталоном float64 по восемнадцати формам, включая простые и сдвинутые на единицу длины последовательностей, так что ядро, неправильно обрабатывающее хвост, проваливается, а не тихо получает хороший результат.

Оценка — ускорение относительно NumPy/BLAS-эталона, замеренного в том же процессе, геометрическое среднее по четырём длинам последовательностей × двум режимам маскирования. 1.0 — паритет с библиотекой. Оценка отношения, а не сырых ГФЛОП/с, делает бенчмарк нечувствительным к тому, что ещё делает машина, — абсолютная пропускная способность на общем ноутбуке колеблется сильнее, чем стоит большинство оптимизаций.

ядро

оценка

посев x_0 (наивное, материализует полную матрицу N×N)

0.19×

базовый уровень NumPy/BLAS — «cuDNN» этой установки

1.00×

развито за 3 шага (отчёт)

2.11×

База знаний охватывает формулировку онлайн-softmax, выбор размера блоков и черепицы, векторизацию CPU, многопоточность и то, как опрашивать хост-машину, а не предполагать архитектуру ISA. Чтобы превзойти BLAS, нужно большинство из них.


Как это работает

Каталог запуска

runs/<run-id>/
  work/              the candidate x_t — a standalone git repo whose history IS the lineage
    .avo/scores.jsonl    every committed version's full score vector
  kb/                the knowledge base K, copied in so paths are stable
  avo-eval           f, as a zero-argument shim the agent can call at will
  NOTES.md           scratch space that survives across steps
  trajectory.jsonl   every step, accepted or rejected
  rejected/          the diff of each rejected candidate, kept for the record
  logs/              evaluator and agent logs

Превращение родословной в git-репозиторий означает, что агент просматривает P_t инструментами, которые он уже знает, — git log, git show v7:attention.c, git diff v6 v7 — вместо специального API. Каждая принятая версия — это коммит с тегом vN, в сообщении которого хранится вектор оценок.

Политика коммитов

Раздел 3.2 статьи: кандидат коммитится только если он проходит проверку корректности и совпадает или улучшает лучший закоммиченный результат на данный момент. Всё остальное откатывается, а его diff архивируется — он остаётся частью внутренней траектории поиска агента, но никогда не попадает в родословную.

Корректность — это порог, а не измерение. Кандидат, не прошедший его, получает ноль независимо от того, что он показал (§3.1). В attention_c это означает, что ядро, которое в 10 раз быстрее и численно неверно, стоит ровно столько же, сколько то, которое не компилируется.

Вектор оценок

f(x) = (f_1(x), …, f_n(x)) — по одному числу на каждую конфигурацию бенчмарка, а среднее геометрическое является максимизируемым скаляром. Именно это делает движение по конфигурациям диагностическим: изменение, которое помогает n1024 и вредит n128, — это блокирующая проблема, а не выигрыш, и один лишь обобщённый показатель скрыл бы её.

Супервизор

В §3.3 статьи: длительные автономные прогоны дают сбой двумя способами — агент застревает, когда исчерпывает текущую линию атаки, или входит в непродуктивные циклы правок, которые продолжают проваливаться. После N шагов без нового рекорда (по умолчанию 3) AVO останавливается и запрашивает перенаправление: реввью всей траектории, предложледнее океискрёт траекторию и предлагает несколько конкретных, отчётливо различных направлений оптимизации. Перенаправление внедряется в следующий вариационный промпт как сильный априори и потребляется ровно одним шагом.

В сессионном режиме супервизор — это та же сессия, только в другой роли, и это достаточно дёшево, чтобы реально использовать. В автономном режиме это отдельный прогон агента с намерением только для чтения.

Траектория

avo plot воспроизводит рисунок 5/6 из статьи: текущее геометрическое среднее как ступенчатую функцию, заполненные кружки на каждом новом рекорде, пунктирные кривые для каждого конфигурации, а базовые значения горизонтальными линиями. Та же оговорка, что и в статье: показана очищенная последовательность, а не внутреннее дерево поиска, просматриваемое между коммитами.


Автономный режим

Чтобы воспроизвести установку из статьи, где оператор — это порождённый агент и никто не наблюдает:

avo run --target attention_c --backend claude_cli --max-steps 40 --time 12h
avo run --resume runs/attention_c-20260321-091500 --time 24h

Бэкенды: claude_cli (Claude Code headless — ближайший аналог агентs/статьи), api (самодостаточный цикл агента на Messages API, для людей, у которых только API-ключ), agent_sdk (внутрипроцессно через claude-agent-sdk) и mock (команда шелы, для проверки механики без модели).

Это расходует квоту или кредиты на каждом шаге. Сессионный режим — нет.


Добавление собственного таргета

Таргет — это директория с target.yaml, стартовая программа, база знаний и эвизитор. Эвалюатор — любой исполняемый файл на языке people; весь контракт — один JSON-объект на stdout:

{"correct": true,
 "metrics": {"config_a": 1520.3, "config_b": 1477.0},
 "error": null,
 "notes": "shown to the agent"}

correct — это шုဧз. metrics — это вектор результатов. Оптимизируемый скаляр — это их среднее геометрическое, если только не задан явный primary.

name: my_target
description: One line, shown in `avo targets`.
seed: seed                 # copied to work/ as x_0
knowledge_base: kb         # copied to the run dir as K
entrypoint: kernel.c       # informational, used in prompts

evaluate:
  command: ["python3", "{target}/eval.py", "--workdir", "{workdir}"]
  timeout: 30m

baselines:                 # optional, measured once before evolution starts
  command: ["python3", "{target}/eval.py", "--baselines"]

score:
  direction: maximize

agent:
  goal: |
    What the agent is actually trying to do, and what the trade-offs are.

Полный контракт — в docs/TARGETS.md, минимально работающий пример — в tests/fixtures/toy/.

База знаний заслуживает серьёзных усилий. Это K в данном контексте; K — это K в Agent(P_t, K, f), и разница между агентом, который заново открывает тiling с нуля за десять шагов, и тем, кто доходит до этого за два.


Что действительно воспроизводится, а что нет

Верно воспроизведено:

  • формула оператора Vary(P_t) = Agent(P_t, K, f) — настоящая агент-программист с редактированием файлов, доступом к оболочке и постоянной памятью, без внесённых изменений задачина дать

  • однотехнология? эволюция с непрерывной линией и git-состоянием (§3.3)

  • шлюз корректности и n-мерный вектор результатов (§3.1)

  • политика поведения «совпадает или лучше», из которой прямые строки ошибочных попыток исключаются (§3.2)

  • вмешательство супервизора при застое и непродуктивных циклах (§3.3)

  • агрегирование по евmetryческому среднему по конфигурациям бенчмарка и графики траекторий (рис. 5/6)

Не воспроизведено намеренно:

  • Аппаратное обеспечение. В статье attention- ядра развиваются на GPU B200, cuDNN и FlashAttention-4 контексты. attention_c — та же задача на CPU, вместе с NumPy/BLAS. Оптимизацияльные приёмы переносятся по типу (tiling, online softmax, векторизация, планирование), но не по масштабируемости.

  • Масштаб. В статье более семи дней, 40 коммитных версий, 500+ изученных направлений. Перidge в сессионном режиме на 10–20 шагов — это демонстрирация, а не восповизводство.

  • Структура популяции. Как и в статье, здесь реализован only single lineage case, чтобы изолировать оператора. Режим на основе архивов и островов совместим с формулировкой, но не реализован.


Структура репозитория

src/avo/
  types.py        Score, LineageEntry, the correctness gate, geomean
  config.py       target specs and run configuration
  lineage.py      P_t as git history
  scoring.py      f as an external process
  knowledge.py    K
  prompts.py      the variation and supervisor prompts — the whole framework/agent interface
  run.py          run state: seed, evaluate, commit policy, trajectory
  session.py      driver: the session you already have is the operator
  loop.py         driver: unattended, spawns an agent per step
  mcp_server.py   the same operations as MCP tools (no dependencies)
  cli.py          the same operations as subcommands
  plot.py         Figure 5/6
  agents/         backends for unattended mode
targets/
  game2048/       policy evolution under a time budget
  attention_c/    kernel evolution — the paper's domain, on a CPU
examples/
  attention-decode-run/  beats Apple's own fused kernel by changing the maths
  attention-c-run/       CPU kernel evolution, with an honest baseline caveat
  attention-metal-run/   GPU prefill — every CUDA instinct measured worse
  game2048-run/          policy evolution — 50x the seed
docs/
  PAPER_MAP.md    every section of the paper, and where it lives in the code
  TARGETS.md      the evaluator contract
  DRIVING.md      how to drive a run from Claude Code, Codex, or a shell
AGENTS.md         cross-agent instructions (read automatically by Codex)
.claude/skills/   the `/avo` skill for Claude Code

Цитирование

Это независимое воспроизведение. Цитируется оригинальная статья:

Распространяется по лицензии Apache-2.0. Не является аффилированным с NVIDIA и не одобрено со стороны NVIDIA.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables bounded, multi-phase coding workflows inside Codex that plan, implement, independently review, repair, and verify repository changes, with an inline dashboard for inspecting runs.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables coding agents to run persistent, budgeted work sessions with dependency graphs, human decision queues, required validation, and clean handoffs for autonomous or human-in-the-loop execution.
    16
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables MCP-compatible clients to delegate multi-step coding tasks to an autonomous subagent that reads outlines, applies validated patches, manages workspace memory, and returns structured results with rollback and cost tracking.
    12
    Apache 2.0