Автономный исследователь на языковых моделях
В отличие от помощника оператора, ожидающего подтверждения на каждую запись в оборудование, система, рассматриваемая в настоящей главе, работает без человека в контуре: она самостоятельно выбирает задачу, самостоятельно ставит эксперимент и самостоятельно пишет статью по полученным результатам.
Назначение системы
Автономный исследователь состоит из большой языковой модели и обвязки, выполняющей полный цикл научной работы. Он находит задачу, разрабатывает методику, ставит эксперимент, анализирует полученные числа и оформляет статью. Специализация узкая, ускорительная: коррекция орбиты пучка, управление магнитными элементами, оптимизация параметров, анализ данных измерений.
Основой служит открытая система AI Scientist, описанная в работе Lu et al. (2024) [43] и адаптированная здесь к ускорителям. Адаптация свелась к одному новому шаблону, размещённому рядом с готовыми шаблонами про языковые модели, диффузию и гроккинг. Шаблон, добавленный в форк, содержит постановку задачи, рабочий код, затравочные идеи и каркас статьи. Ничего специфически ускорительного в самой обвязке нет: вся физика сосредоточена в шаблоне, подключаемом по имени каталога.

Схема делит работу на три стадии. На первой модель формулирует идею, проверяет её на новизну поиском по литературе и помещает в архив с оценками. На второй идея превращается в код: правки в experiment.py вносит aider, редактор, управляемый моделью, а обвязка запускает переписанный код и возвращает модели напечатанные числа. Третья стадия собирает статью из каркаса LaTeX, после чего отдельный проход рецензирует написанное. Пунктирная стрелка, замыкающая схему, возвращает накопленные идеи в начало, так что следующая идея формулируется с учётом уже проверенных.
Каждая идея, взятая из архива, отрабатывается в отдельном каталоге, куда копируется весь шаблон целиком. Ни один прогон не изменяет исходный каталог, и любой результат, полученный системой, остаётся воспроизводимым: рядом с числами сохраняются и код, приведший к ним, и полная переписка с моделью, записанная построчно.
Постановка задачи
Всё, что системе известно о предметной области, взято из файла prompt.json. Роль и цель, поставленные перед моделью, заданы в нём первыми двумя полями.
System: You are an AI scientist specializing in accelerator physics and
beam dynamics with expertise in machine learning applications for particle
accelerator control systems. Your knowledge spans MAD-X simulations, beam
position monitoring (BPM) systems, and both traditional (SVD-based) and
AI-driven orbit correction methods.
Task: Minimize orbit deviations in the accelerator by optimizing corrector
magnet settings using a combination of numerical optimization and machine
learning techniques.
В том же файле перечислены требования, ограничивающие решение, и среда, в которой рассчитывается орбита.
"technical_requirements": [
"Process beam position data from 16 BPMs (x/y coordinates)",
"Account for hidden misalignment parameters affecting magnetic elements",
"Maintain magnet currents within ±7A operational limits",
"Achieve orbit residuals below 1e-4 m at all BPMs"
],
"simulation_environment": {
"tool": "MAD-X",
"configurations": [
"vepp5_full.seq lattice",
"0.4 GeV electron beam energy",
"Error definitions: ealign with tgauss-distributed displacements"
]
}
Это задача, разобранная в главе про коррекцию равновесной орбиты: 16 датчиков положения, дающих по две координаты, предел корректора \(\pm 7\) А, модель накопителя ВЭПП-5. Разница заключается в том, что ставится она не человеку, а программе.
Смещения магнитных элементов, названные в требованиях «hidden», разыгрываются внутри модели и решателю не сообщаются, поэтому судить о них можно только по орбите, измеряемой в мониторах. Порог в \(10^{-4}\) м записан там же, и по нему система оценивает как свои прогоны, так и базу, рассчитанную заранее.
Сам шаблон представляет собой обычный каталог, размещённый среди прочих.
templates/closed_orbit_correction/
├── prompt.json постановка задачи и системная роль
├── seed_ideas.json пять затравочных идей
├── experiment.py расчёт орбиты и коррекция по SVD
├── plot.py графики по собранным результатам
├── vepp5_full.seq оптика ВЭПП-5, читаемая MAD-X
└── latex/ каркас статьи
Прогон запускается командой python launch_scientist.py --experiment closed_orbit_correction, после чего участие человека не требуется до самого конца. Каталог результатов, названный по метке времени и имени идеи, создаётся в начале работы.
Точка отсчёта
Вместе с постановкой модели выдаётся работающий код, служащий одновременно образцом и базой сравнения. Ускоритель инициализируется через cpymad, пучок электронов задан с энергией 0.43 ГэВ, в постановке округлённой до 0,4 ГэВ, а ошибки расстановки квадруполей разыгрываются директивой ealign с гауссовым распределением, усечённым на двух с половиной сигмах. Орбита снимается в шестнадцати мониторах, отобранных по классу monitor. Коррекция выполнена классически, через псевдообратную матрицу отклика с отсечением малых сингулярных чисел.
def correct_orbit(self):
elem_val_limit = 7
svd_cutoff = 1e-3
target_orbit = np.zeros(2 * self.num_bpms)
matrix = self.calculcate_resp_mat()
inv_mat = np.linalg.pinv(matrix, rcond=svd_cutoff)
madx = self.start_madx()
x, y = self._get_orbit(madx)
current_orbit = np.concatenate((x, y))
tmp_elem_val = -inv_mat.dot(current_orbit - target_orbit)
tmp_elem_val = np.clip(tmp_elem_val, -elem_val_limit, elem_val_limit)
elems_deltas = dict(zip(self.globals.keys(), tmp_elem_val))
self.change_elements(elems_deltas)
x, y = self._get_orbit(madx)
self.stop_madx(madx)
return x, y, elems_deltas
Матрица отклика здесь не берётся из модели, а измеряется: каждый корректор смещается на шаг вверх и вниз, а разность откликов, снятых в мониторах, делится на этот шаг. Так же поступают и на реальной машине. Ограничение np.clip по \(\pm 7\) А расположено внутри алгоритма, до подачи токов, а не в проверке, добавленной после него. Опечатка в имени calculcate_resp_mat оставлена без изменений, поскольку на неё опирается код, написанный системой позже.
Этот файл модель видит целиком, вместе с постановкой. Идеи, предложенные далее, сформулированы в терминах уже написанных методов: «доработать correct_orbit», «добавить в calculcate_resp_mat выбор подмножества корректоров».
Идеи, придуманные системой
Пять затравочных идей содержатся в seed_ideas.json, и модель дополняет их новыми, читая постановку и код. В запрос включается весь архив, накопленный к этому моменту, чтобы новая идея не повторяла предыдущие. Каждая идея описана коротким планом эксперимента и снабжена тремя оценками от одного до десяти: интересность, выполнимость и новизна. Оценки выставляет сама модель, следуя указанию, включённому в запрос: быть осторожной и реалистичной.
Сформулированное проходит через три раунда правки, в которых модель перечитывает и улучшает собственный ответ, а когда улучшать нечего, ответ помечается словами I am done. Затем идея проходит проверку на новизну: модель формулирует поисковые запросы, получает по десять статей с аннотациями из Semantic Scholar или OpenAlex и выносит вердикт строкой Decision made: novel. На решение отведено десять раундов, однако обычно достаточно двух-трёх. Идеи, признанные несамостоятельными, до эксперимента не допускаются.
Ниже приведены идеи, предложенные системой по коррекции орбиты.
| Идея | Int./Feas./Nov. |
|---|---|
| Hybrid SVD-Neural Network Correction Framework. Каскад: грубая коррекция по SVD, затем нейросеть, обученная на остатках. Сравнить чистые NN и SVD с гибридом. До 100 000 особей и до 10 итераций | 9 / 7 / 8 |
| Genetic Algorithm for Optimizing Orbit Correction. Генетический алгоритм с отбором, скрещиванием и мутацией для настройки корректоров. Сравнить норму \(L_2\) и время счёта с SVD и NN | 9 / 8 / 9 |
| Predictive Control Using LSTM-Based Forecasting. Предсказание положения пучка по истории BPM и упреждающая подстройка корректоров до появления отклонения | 9 / 5 / 9 |
В работу была принята первая из них.
Эксперимент
Идею принимает цикл, отмеряющий системе лимит попыток. Прогонов по умолчанию не более пяти, неудачных заходов подряд не более четырёх, и работа, не завершённая в отведённых рамках, прерывается.
Для гибридной коррекции лимит был увеличен: прогоны отличаются только числом итераций сети, и пяти для такой развёртки недостаточно; рисунок ниже собран из одиннадцати прогонов, от нулевой итерации до десятой.
MAX_ITERS, MAX_RUNS = 4, 10
def perform_experiments(idea, folder_name, coder, baseline_results) -> bool:
current_iter, run = 0, 1
next_prompt = coder_prompt.format(
title=idea["Title"], idea=idea["Experiment"],
max_runs=MAX_RUNS, baseline_results=baseline_results,
)
while run < MAX_RUNS + 1:
if current_iter >= MAX_ITERS:
break
coder_out = coder.run(next_prompt)
if "ALL_COMPLETED" in coder_out:
break
return_code, next_prompt = run_experiment(folder_name, run)
if return_code == 0:
run += 1
current_iter = 0
current_iter += 1
Каждый прогон запускается как python experiment.py --out_dir=run_i, и модель получает обратно либо рассчитанные средние из final_info.json, либо последние полторы тысячи знаков stderr. Завершившийся с ошибкой прогон не прерывает работу, а возвращается модели текстом ошибки, по которому она исправляет код. Каталог неудачного захода при этом удаляется, чтобы незавершённые результаты не попали в статью. Результаты, признанные пригодными, дописываются в notes.txt вместе с описанием прогона, и оттуда их впоследствии берёт стадия написания статьи. Код, исполняемый на этом шаге, написан языковой моделью, поэтому авторы системы рекомендуют изолировать прогон в контейнере, и Dockerfile для этого включён в репозиторий.
По окончании расчёта той же модели поручается переписать plot.py и перечислить в нём прогоны, заслуживающие графика. Заголовки, подписи осей и легенда выбираются на этом шаге, а подробное описание каждого графика заносится в те же заметки.
Код гибридной коррекции система написала самостоятельно. Сеть в нём обучается не отображению «орбита — токи» целиком, а поправке к решению, найденному через SVD, и эта поправка накапливается по итерациям.
def hybrid_correct_orbit(self, model=None, iterations=0, svd=True):
elem_val_limit = self.corr_limit
x_new, y_new, elems_deltas = self.correct_orbit() # грубая коррекция
R = np.concatenate((x_new, y_new))
if model is None:
return x_new, y_new, elems_deltas
dI_nn_total = np.zeros(len(self.globals)) + list(elems_deltas.values())
for it in range(iterations):
dI_nn = model.predict(R.reshape(1, -1))[0] # поправка по остатку
dI_nn_total += dI_nn
dI_nn_total = np.clip(dI_nn_total, -elem_val_limit, elem_val_limit)
self.change_elements(dict(zip(self.globals.keys(), dI_nn_total)))
madx = self.start_madx()
x_new, y_new = self._get_orbit(madx)
self.stop_madx(madx)
R = np.concatenate((x_new, y_new))
return x_new, y_new, elems_deltas
Обучающая выборка набиралась отдельным прогоном: 100 000 случайных расстроек, для каждой из которых снят остаток после SVD и рассчитана идеальная добавка по номинальной матрице отклика, измеренной без расстроек. Сеть выбрана простая, MLPRegressor с двумя скрытыми слоями 64 и 32, а обученная модель сохранена в nn_model.joblib и далее только читается. Прогоны с первого по десятый отличаются одним числом — количеством итераций сети, извлечённым из имени каталога.

На рисунке приведены одиннадцать пар столбцов, по паре на прогон, шкала логарифмическая. Синий столбец — начальная невязка \(\sum (x_i^2 + y_i^2)\) в м², оранжевый — остаточная, а планки погрешностей, построенные по стандартной ошибке среднего, показывают разброс. В каждом прогоне сто независимых расстроек, разыгранных заново, поэтому начальная невязка остаётся примерно одинаковой от прогона к прогону, и оранжевые столбцы сравнимы между собой. Нулевая итерация, рассчитанная без сети, соответствует чистому SVD: \(1.9 \cdot 10^{-4}\) м² до коррекции и \(4.8 \cdot 10^{-5}\) после. Три итерации сети дают \(5.9 \cdot 10^{-6}\), что является лучшей точкой на графике. К десятой итерации остаток возвращается к \(3.5 \cdot 10^{-5}\).
Статья и рецензия
Написанием статьи занимается тот же aider, но с другим набором файлов, открытых для правки: код эксперимента, заметки и latex/template.tex. Ссылки, вставляемые в текст, система находит самостоятельно тем же поиском по литературе. Готовый PDF собирается pdflatex, а chktex проверяет разметку. Ошибки сборки, найденные этими программами, возвращаются модели тем же способом, что и ошибки расчёта.
Последним включается рецензент. Статья, преобразованная обратно в простой текст, подаётся модели с формой отзыва в стиле NeurIPS, в которой необходимо выставить оценки за оригинальность, качество, ясность и значимость, дать общую оценку от одного до десяти и вынести решение Accept или Reject. Собирается пять отзывов, которые сводятся мета-рецензентом; температура установлена равной 0.1. Статья про гибридную коррекцию, оценённая собственным рецензентом на 3 из 10, была им же отклонена.
Ограничения и перспективы
Ниже перечислены ограничения, признанные за системой.
- Отсутствие работы с изображениями. Модель читает только числа и текст, а построенные графики не анализирует.
- Неверная реализация идей. Написанный код нередко не соответствует тому, что задумано в описании эксперимента.
- Ошибки в численном анализе. Величины, сравниваемые между собой, модель путает, а выводы по таблицам даются ей плохо.
- Ограниченная физическая интерпретация. Система работает с формой задачи, а не с её содержанием.
Направления, названные для дальнейшей работы: мультимодальные модели, способные читать графики; специализированные модули под предметную область; интеграция с реальными установками; развитие самих языковых моделей, лежащих в основе.
Полезные ссылки
- AI Scientist, исходная система, и статья Lu et al. (2024), arXiv:2408.06292.
- AI Scientist v2, следующая версия, заменившая шаблоны поиском по дереву экспериментов.
- Форк с шаблоном по коррекции орбиты, откуда взяты листинги этой главы.
- MAD-X и cpymad, на которых рассчитывается оптика ВЭПП-5.
- aider, редактор, вносящий правки в код по указаниям модели.
- Глава про коррекцию равновесной орбиты разбирает ту же задачу вручную, а глава про нейронные сети — устройство
MLPRegressor.