Эксперименты · Воспроизводимость
Weight-space programming: как воспроизвести эксперимент редактирования весов модели

Weight-space programming — это способ программировать поведение модели через прямое изменение её параметров или промежуточных представлений, не запуская обычный цикл градиентного обучения. В типичном эксперименте агент получает доступ к модели через сервис forward pass, предлагает изменения весов, проверяет их на задачах и оставляет только те варианты, которые улучшают заданную метрику.
Главная сложность воспроизведения здесь не в том, чтобы получить похожий график. Нужно восстановить сам экспериментальный цикл: какие веса доступны, сколько запросов разрешено, как считается качество, какие данные видит агент и на каком наборе проверяется итоговый вариант. Если хотя бы один из этих элементов не зафиксирован, результат нельзя честно сравнивать с заявленным.
Что именно нужно воспроизвести
До запуска разделите публикацию или репозиторий на четыре слоя:
- Объект редактирования. Полная модель, отдельный слой, матрица, bias, low-rank-представление или внешний файл дельт.
- Интерфейс оценки. Forward pass, логиты, вероятности, ответы на заранее заданные промпты или агрегированная метрика.
- Контур поиска. Код, который предлагает изменения, выбирает кандидатов и решает, принять ли новую версию.
- Протокол измерения. Набор задач, seed, число итераций, лимиты запросов, критерии остановки и holdout-набор.
Полезно вести отдельную таблицу конфигурации. В ней должны быть указаны идентификатор модели, точность вычислений, устройство, размер редактируемой области, начальное состояние, seed, лимит forward pass, лимит токенов агента и точная формула метрики.
Минимальная архитектура harness
Для безопасного воспроизведения достаточно пяти изолированных компонентов:
model/
checkpoint/
candidate_state/
harness/
forward_service.py
evaluator.py
search_loop.py
budget.py
data/
train_tasks.jsonl
holdout_tasks.jsonl
runs/
config.json
events.jsonl
summary.json
forward_service загружает модель и принимает запрос вида «состояние весов + входной текст». Он не должен сам решать, какой кандидат лучше. evaluator превращает ответы в числовую метрику. search_loop управляет предложениями агента и применением дельт. budget централизованно запрещает превышение лимитов.
Такое разделение важно для аудита: можно заменить агента на случайный поиск или вручную заданные дельты и проверить, не скрывается ли улучшение в оценщике или в особенностях сервиса.
Шаг 1. Зафиксируйте окружение и исходное состояние
Начинайте с чистого окружения и не скачивайте произвольные скрипты в каталог проекта. Команды ниже являются шаблоном: имена файлов и зависимости нужно сверить с опубликованным harness.
python -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python --version
python -m pip freeze > runs/pip-freeze.txt
git rev-parse HEAD
Проверьте контрольную сумму исходного checkpoint и сохраните конфигурацию в отдельном файле. Не изменяйте оригинальные веса на месте:
cp config.example.json runs/config.json
cp -a model/checkpoint model/checkpoint.original
sha256sum model/checkpoint/* > runs/checkpoint.sha256
Если checkpoint состоит из большого числа файлов или хранится в другом формате, используйте штатную утилиту проекта. Цель шага — иметь возможность доказать, что baseline и все кандидаты стартовали из одного состояния.
Шаг 2. Поднимите forward-pass сервис
Сервис должен быть максимально простым и детерминированным. Он принимает вход, применяет указанную дельту к копии состояния или загружает версию кандидата, выполняет forward pass и возвращает только необходимые выходы. В production-среде такой API требует аутентификации и ограничения размера запроса; для локального эксперимента не публикуйте его наружу.
python harness/forward_service.py \
--model model/checkpoint.original \
--host 127.0.0.1 \
--port 8000 \
--dtype bf16
В отдельном терминале выполните health-check, если он предусмотрен harness:
curl --fail --silent http://127.0.0.1:8000/health
Затем отправьте один фиксированный тестовый запрос. Сохраните ответ и время выполнения в журнал. Повторный запрос с теми же параметрами должен давать тот же результат или документированно отличаться из-за недетерминированности GPU.
Шаг 3. Восстановите цикл предложения и проверки
Общий цикл выглядит так:
- Агент получает описание разрешённой области редактирования и текущую метрику.
- Агент предлагает дельту или новое состояние параметров.
- Harness проверяет форму, dtype, диапазон и размер дельты.
- Forward-pass сервис считает ответы на рабочем наборе.
- Оценщик вычисляет метрику и записывает все входы и выходы.
- Правило принятия сохраняет кандидата или отклоняет его.
В журнале каждой итерации должны быть как минимум:
{
"iteration": 7,
"candidate_id": "cand-0007",
"parent_id": "cand-0006",
"edited_tensors": ["layer.12.mlp.down_proj.weight"],
"forward_passes_used": 18,
"metric_before": 0.42,
"metric_after": 0.47,
"accepted": true,
"reason": "improved_train_metric",
"seed": 1234
}
Не записывайте в общий журнал секреты, токены доступа и полные пользовательские данные. Для отладки достаточно идентификаторов задач, хешей входов и агрегированных результатов.
Как зафиксировать бюджет
Бюджет должен быть частью кода, а не договорённостью в README. Минимальный набор ограничений:
- максимальное число forward pass;
- максимальное число итераций поиска;
- максимальное число токенов или вызовов агента;
- максимальный размер дельты и число редактируемых параметров;
- лимит времени и памяти;
- фиксированное число повторов для оценки.
python harness/search_loop.py \
--config runs/config.json \
--max-iterations 100 \
--max-forward-passes 2000 \
--max-delta-elements 100000 \
--seed 1234 \
--run-dir runs/experiment-001
Принудительно завершённый процесс не должен считаться успешным. В summary.json явно указывайте причину остановки: budget_exhausted, converged, error или completed.
Как проверять результат
Проверка должна идти в три прохода.
1. Baseline
Прогоните исходную модель на рабочем и holdout-наборе. Это отвечает на вопрос, было ли вообще что улучшать. Если baseline уже считается с ошибкой или меняется между запусками, продолжать поиск рано.
2. Рабочий набор
Оцените кандидатов на задачах, которые разрешены алгоритму поиска. Сравнивайте не только лучший результат, но и кривую качества по бюджету: сколько forward pass потребовалось до первого улучшения и сколько кандидатов было отвергнуто.
3. Отдельный holdout
После выбора финального кандидата заморозьте его и один раз запустите на отдельном наборе. Агент и правило принятия не должны видеть эти примеры во время поиска. Сохраните список идентификаторов задач, версию оценщика и конфигурацию запуска.
python harness/evaluator.py \
--model model/checkpoint.original \
--candidate runs/experiment-001/final \
--tasks data/holdout_tasks.jsonl \
--output runs/experiment-001/holdout.json \
--seed 1234
Если улучшение есть только на рабочем наборе, это не доказательство успешного редактирования. Возможны переобучение на формулировки, утечка задач в промпт агента или слишком гибкое правило остановки.
Что считать воспроизведением
Разумно различать три уровня результата:
- Запущен код. Harness выполняется, сервис отвечает, журналы создаются.
- Воспроизведён протокол. Совпадают модель, данные, бюджет, seed, область редактирования и правила оценки.
- Воспроизведён эффект. На независимом наборе наблюдается сопоставимое изменение метрики с оговорённой вариативностью.
Первый уровень не подтверждает второй, а второй не гарантирует третий. Если исходные данные, checkpoint или закрытый компонент недоступны, честный результат — «протокол частично восстановлен», а не «эксперимент повторён».
Типовые ошибки
- Агент редактирует не те веса
- Проверьте имена тензоров после загрузки, форму матриц и хеш состояния до и после применения дельты.
- Метрика растёт из-за оценщика
- Запустите оценщик на сохранённых ответах и сравните его с независимой реализацией хотя бы на небольшой выборке.
- Holdout оказался частью поиска
- Разделите файлы задач на уровне процесса и запретите агенту получать их содержимое, даже через сообщения об ошибках.
- Бюджет считается неполно
- Учитывайте повторные forward pass, ретраи, warm-up и вызовы для проверки кандидата. Счётчик должен находиться рядом с клиентом сервиса.
- Результат нельзя повторить
- Сохраните seed, версии библиотек, dtype, параметры генерации, порядок задач и финальную дельту. Для GPU отдельно отметьте режимы детерминизма.
- Процесс повреждает baseline
- Работайте с копиями или неизменяемыми snapshot-файлами. Финальный кандидат должен ссылаться на родительское состояние.
Ограничения метода и эксперимента
Редактирование весов без градиентного обучения не означает отсутствия оптимизационного поиска. Агент всё равно тратит вычислительный бюджет на подбор и проверку кандидатов. При малом бюджете поиск может не найти рабочую дельту; при большом — переобучиться на рабочий набор.
Кроме того, изменение одного слоя может непредсказуемо затронуть другие способности модели. Нельзя делать вывод о «редактировании знания» по одной метрике или нескольким демонстрационным ответам. Нужны тесты на целевое поведение, сохранность соседних навыков, устойчивость к перефразированию и перенос на независимые задачи.
Наконец, forward-pass сервис скрывает часть стоимости эксперимента. Логи, сериализация дельт, загрузка checkpoint и повторные запуски могут быть существенны даже тогда, когда в статье учитывается только число запросов к модели.
Итоговый чек-лист
- Исходный checkpoint идентифицирован и не изменяется.
- Область редактирования и формат дельты задокументированы.
- Forward-pass сервис работает локально или защищён от внешнего доступа.
- Рабочий и holdout-наборы физически разделены.
- Лимиты forward pass, токенов, итераций и времени считаются кодом.
- Каждый кандидат имеет родителя, хеш и запись решения.
- Baseline измерен до поиска.
- Финальный кандидат проверен на независимом наборе.
- Ограничения и недоступные части исходного эксперимента перечислены явно.
Для соседних тем см. раздел guides и глоссарий Agent Lab Journal.