Привет, друзья! Я, похоже, наконец пережила кризис пришествия агентов в нашу жизнь. Мне всегда безумно нравился процесс решения задач — этакий личный, удивительный мир, даже когда ты уже знаешь правило Лопиталя/Modus ponens/выберите то, которое заставило вас смеяться больше всего при изучении.

А теперь, чтобы не выпасть из жизни, задачи просто приходится решать с кем-то. И этот кто-то LLM-Agent.

По жизни я — XAI Researcher, так что эта статья, среди прочих, будет практическим туториалам для решения задачи "собрать агента для интепретируемости ML моделей и больше никогда не смотреть в экран, думая о коэффициентах логистической регрессии".

Или всё-таки подумать придётся?
Весь код туториала лежит здесь: https://github.com/SadSabrina/XAI-open_materials/tree/main/naive_agent_and_xai

source: unsplash
source: unsplash

Немного введения

Чтобы не ходить далеко, подтянем основные понятия.

Определения:

LLM Agent — система, в которой большая языковая модель является двигателем. Кто как — а я вижу агента как множество, состоящее из примерно 4х компонент: \{M, T, S, R\}

где:

* M — сама LLM;

* T — набор инструментов (tools), которые агент умеет вызывать;

* S — состояние системы: память, история действий, промежуточные результаты;

* R — reasoning loop, то есть цикл рассуждений и принятия решений.

Математика в статье на этом закончилась, но эту постановку, всё же, давайте запомним.

Explainable AI — набор методов и подходов, которые помогают анализировать поведение моделей (LLM и ML, но в данной статье мы будем смотреть только на ML). Матемтически каждый метод можно определить по своему, поэтому этим мы сейчас заниматься не будем.

source: unsplash
source: unsplash

Контекст:

Большинство (ладно, все) XAI-подходов исторически создавались для человека. Мы сидели и пытались понять, почему оно работает. Частные ML-методы: SHAP values, feature importance, partial dependence plots, ICE предполагают, что дальше в процесс интерпретации включается человек, который умеет думать, смотреть на графики/коэффициенты и знает, что такое доверительный интервал.

Сегодня, любой процесс, который можно разбить на step-by-step (и он не касается того, что шаг вправо — и пациента уже можно не зашивать (простите)), сегодня можно автоматизировать. Это же коснулось и интерпретируемости, неформально "родив" agentic XAI — подходы, в которых LLM объясняет модель.

Улучшить объяснение агента можно многими способами:

  • для человека: выйти погулять и зайти обратно;

  • для LLM: сделать больше reasoning циклов.

  • для человека: найти другого человека и выполнить с ним брейншторм;

  • для LLM: выполнить критику своего решения.

Но больше — не равно лучше, автоматически и быстро - не равно дешево и сердито. У агентов есть режимы провала — то есть места, где всё работает ну вообще не так, как надо. Например, p-hacking (LLM-агент автоматически перебирает аналитические решения, пока не получит статистически значимый результат), missing sanity checks (агент пропускает базовые проверки корректности данных, эксперимента или модели), или, более доступная трудовым будням — unreliable LLM-driven annotation (LLM ненадежно размечает данные или интерпретирует результаты исследования, создавая шум, bias или фиктивные выводы).

Данная статья задумана как пример "норм" interpretability pipeline на базе агента. Мы:

  1. обучим baseline-модель;

  2. добавим SHAP и feature attribution;

  3. построим наивного, но всё же хорошего, interpretability-agent;

  4. построим менее наивный multi agent pipeline;

  5. посмотрим на failure mode (который соберем сами).

Поехали.

Дизайн: агент

Мы будем использовать LangChain и ничего приятнее этого фреймворка нет. Так что, чтобы не просто посмотреть на простой код (ура, тавтология), рассмотрим вполне себе эксперимент. У нас будет две версии задачи.

Первая — baseline: обычная модель на стандартном датасете breast_cancer. На ней мы проверим, способен ли agentic pipeline в принципе собрать адекватный XAI-отчет: посчитать качество модели, посмотреть feature importance, SHAP и локальное объяснение — объяснение на одном примере.

Вторая — batch artifact: та же задача, но с дополнительным признаком, который имитирует артефакт сбора данных. В реальном мире это мог бы быть номер больницы, лаборатории, прибора, партии измерений или источника данных. Такой признак может сильно коррелировать с target не потому, что он несет содержательный сигнал, а потому что данные так были собраны. В хорошем случае, если уж мы автоматизировали наш ML агент должен это увидеть.

Для каждой версии задачи также у нас будет три варианта pipeline.

Naive agent

Naive agent - обычный агент с tools. Мы запустим его в двух версиях — с подробными инструкциями (02.1_naive_interpretability_agent.py), и с инструкциями zero-shot вида (02.0_naive_interpretability_agent.py). Для обоих случаев, агент сможет сам вызывать функции для расчета метрик, sanity checks, feature importance, SHAP и локального объяснения. Схематический вид обоих:

LLM + tools + свобода действий (не шибко ограниченный system prompt)

LLM + tools + свобода действий (ограниченный system prompt)

Полагая в контексте только system prompt, агент решает какие инструменты вызвать, в каком порядке, когда остановиться, как собрать финальный interpretability report.

Запуск:

python 02.*_naive_interpretability_agent.py

Внутри агенту даны следующие tools (файлы tool_helpers.py, agent.py):

  1. model_performance — считает train/test quality и generalization gap (разница между трейн и тест качетсвом);

  2. sanity_checks — проверяет базовые свойства данных (а мы с вами знаем, что агенты страдают без этого шага);

  3. feature_importance — достает impurity-based importance из леса;

  4. shap_explanation — считает global/local SHAP;

  5. explain_single_prediction — объясняет одно предсказание модели.

С точки зрения LangChain это просто tool-calling pipeline: LLM получает задачу, вызывает функции и постепенно строит reasoning trace. С точки зрения XAI — tools обеспечивают покрытие необходимого и достаточного анализа для леса в такой постановке.

Примечение:

Будете смотреть код, обратите внимание на гиперпараметр recursion limitв файлах запуска экспериментов (02-04). Он режет количество итераций, в которые агент предпринимает шаги, ведь агент — это как воскресенье перед понедельником на диете — последний пончик никогда не будет последним. В нашем случае мы специально ограничиваем число итераций в конфиге и бережемся от покупки новых штанишек: config={"recursion_limit": 12}.

Идея шага — посмотреть, что получится, если дать LLM-агенту инструменты и сказать: “Проанализируй модель”. Это простой естественный сценарий и наши вопросы к нему : "Как агент использовал tools?", "Увидел ли ограничения в инструкциях?" и "Как слепил отчет?"

Manual agent pipeline

Тут все tools запускаются детерминированно (файл 03_manual_pipeline_with_shap.py), а LLM получает уже готовые результаты и только пишет отчет.

Этот эксперимент — тоже baseline, но только уже для pipeline c агентом. Спускаемся на уровень ниже, убираем часть автономности, получаем воспроизводимость: одинаковые проверки, одинаковые входные данные.

LLM + контекст + задача проанализировать (summarization + interpretation + writing)

Запуск:

python 03_manual_pipeline_with_shap.py

Вопрос тут: Помогает ли фиксированный порядок проверок не пропустить важные детали или режим "гуляй сам" — нормальный?

Multi agent pipeline

Multi-agent pipeline - эксперимент, как вы, уверена, неожиданно догадались —  из 3 агентов (04_multi_agent_system.py). Один — аналитик, второй — критик, третий — отчетное лицо. Ну и по определению — аналитик отвечает за первичную интерпретацию модели, критик ищет слабые места, а отчетник собирает финальный текст. Все роли задает системный промт.

Запуск:

python 04_multi_agent_system.py

Идея — в разделении ролей. Если один агент одновременно анализирует, критикует и пишет финальный отчет, ему, кажется, легко пропустить собственные ошибки. Multi-agent pipeline делает критику частью процесса (и не говорите, что у вас уточки на столе не стояло!). Вопросы сюда: поймал ли critic-agent batch artifact и улучшился ли финальный отчет?

Примечание: дизайн XAI

Почему агенту даны такие тулы и не дано меньше или больше? Это связано с постановкой задачи. Мы работаем с RandomForestClassifier, поэтому берем несколько способов интерпретации модели — внутренний и внешний, а также несколько уровней — локальный и глобальный. У каждого есть свои ограничения, но этой пары нам достаточно.

feature_importance в случае леса — это impurity-based importance: насколько признак помогал уменьшать неопределенность при разбиениях деревьев. Метод быстрый, встроенный и хорошо показывает, на что модель в среднем опирается глобально. Его нюансы: importance может быть нестабильной на коррелированных признаках, а признаки с большим количеством уникальных значений (говорят также — с высокой кардинальностью) могут получать искусственно завышенную важность.

SHAP values — внешний метод, основанный на задаче оптимального распределения выигрыша. Упрощая — мы распределяем вклад между признаками, добавляя и удаляя их из множества. SHAP также дает нам два уровня — вклад конкретное предсказание модели и global SHAP — усреднение по датасету. Наюнсы SHAP таковы: значения чувствительны к распределению данных, коррелированным признакам (хотя менее важности леса) и выбранному background distribution. Это тоже надо учитывать — и классный агент должен это уметь.

Далее, локальный и глобальный уровень мы используем просто для двух разных вопросов.

  1. global interpretation → чему модель научилась в среднем (среднее по больнице всегда 36.6);

  2. local interpretation → почему модель приняла конкретное решение для одного объекта.

Теперь, вооружившись этим багажом, давайте оценим, что дадут агенты в каждой постановке.

source: unsplash
source: unsplash

Анализ

После последовательного запуска скриптов, у нас получится 7 прогонов и папки repots и artifacts наполняется своими данными. До run агентских скриптов вам надо пройти и заменить префикс на интересующий эксперимент, а также запустить трейн моделей (файлы 01_train_model.py, 05_batch_exp.py).

python 01_train_model.py
python 05_batch_exp.py

После запуска в artifacts/ появятся:

  1. обученная модель;

  2. train/test данные;

  3. metadata;

  4. базовые performance-метрики.

Они дальше идут агентам.

Артефакты запусков
Артефакты запусков

Baseline

Рассмотрим получившийся файлик для baseline наивного агента с наивным промтом reports/02_naive_agent_report_zero_shot_baseline.md.

Как видим, в отчете обозначены секции. Структура (заявленная агентом):

sanity checks → метрики → feature importance → SHAP

На shap агент поломался. Для чистоты пытаться починить мы это не будем, но всё же отметим.

Итого из хорошего у нас то, что агент без подробных инструкций последовательно использовал tools и собрал структурированный (в зародыше, но!) отчет.

При этом качество осталось поверхностным — сломанный shap нас в реальной жизни не устроил бы. У этого момента может быть две причины — сопосбности агента и недостаточность инструкций. Давайте попробуем это пофиксить, и дадим больше контекста.

Baseline + system prompt

Naive agent с подробным prompt уже заметно лучше zero-shot версии. Он начинает интерпретировать результаты: связывает importance с клиническим смыслом признаков, сопоставляет impurity importance и SHAP, пишет про generalization gap и ограничения тестовой выборки. На мой вкус - агент шикарно отмечает ограничения — potential collinearity, single‑model view, feature‑importance bias — и в целом пункты 1-6 — обоснованы..

Однако, есть и минусы. Например, в блоке 3 (глобальная интерпретация), агент заявляет:

These are known clinically to be strong discriminators between malignant and benign breast lesions

Это, в целом, разумно и может быть правдой, однако тут агент немного вылез за полномочия — играть в медика его мы не просили. Простим и посмотрим линейную версию, где у агента задача только саммаризации.

Baseline + system prompt + controlled tool calling

Жизнь нас уже научила, поэтому попросим у агента хорошие секции сразу:

  1. Short summary - summary: что это за модель и можно ли ей в целом доверять.

  2. Performance - качество модели: train/test metrics, generalization gap, ошибки классификации.

  3. Sanity checks - базовые проверки данных.

  4. Global interpretation - глобальная интерпретация модели через feature importance: чему модель научилась “в среднем”.

  5. SHAP interpretation - глобальные и локальные SHAP explanations: какие признаки вносят вклад в predictions.

  6. Local explanation - разбор конкретного объекта и причин конкретного предсказания модели.

  7. Limitations - ограничения интерпретации и потенциальные угрозы валидности выводов.

  8. What to check next - какие дополнительные проверки, эксперименты или validation steps стоило бы сделать дальше.

В такой постановке интересное, чем в нас плюнул агент — ограничение в виде дисклеймера:

Prepared by the interpretability analysis agent, using only the supplied model diagnostics.

И это прекрасно. Вообще, модельки не редко плюют дисклеймеры, что спасает нас от забывания о критическом мышлении. В остальном, этот прогон тоже хорош - агент не начал галлюцинировать и довольно аккуратно разделил performance, SHAP, local explanations и limitations. Более того, он опять (ещё бы — та же модель) верно поднял проблемы feature-importance bias, potential collinearity, calibration и external validation.

Но одновременно с этим — ура, можно придираться. Агент рекомендует действия и часть из них хороша — советы про calibration или PDP/ICE plots вполне разумны. Но вот PCA тут уже не совсем нужен корреляцию мы могли бы посмотреть, изначально, проще. Решит ли эту проблему внешний критик?

Multi-agent pipeline + system prompt

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

  • analyst-agent интерпретирует модель;

  • critic-agent ищет слабые места;

  • reporter-agent собирает финальный narrative.

По отчету видно, что критик очень сильно снижает "серьезность и тон" выводов. Проводя аналогию — выступает в роли душного скептика, кем нужно быть в анализе данных и моделей. А ещё критик видит все проблемы, упомянутые ранее и очень широко их расписывает. Это и плюс и минус. Сложнее читать, легче запутаться.

Таким образом, мы увидели, что разделение ролей действительно делает interpretability pipeline лучше. Но вместе с этим, мы:

  • увеличили complexity, latency, стоимость reasoning...

и налили воды.

Закинем явную ошибку: batch artifact

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

reports/02_naive_agent_report_batch_artifact.md
reports/03_manual_pipeline_report_batch_artifact.md
reports/04_multi_agent_report_batch_artifact.md 

Ситуация получилась хорошей — все три pipeline заметили проблему. Даже naive-agent довольно быстро начал подозревать, что collection_batch выглядит не как предметный признак, а как артефакт сбора данных. Отличия лишь в рзамере отчета и уверенности, где multi-agent pipeline напараноил от души. Напредлагам нам и необходимость group-aware validation и проверку performance across batches. Потом его поправил наш reporter, но опять же — мы получили тонну воды, а ещё код для воспроизведения в конце.

source: https://simonw.substack.com/p/i-think-agent-may-finally-have-a

Выводы

Итак, сейчас мы с вами увидели несколько моментов в действии.

Во-первых, даже простые agentic XAI pipelines уже способны собирать вполне разумные interpretability reports. Учтем также, что все эксперименты выше работали на бесплатной gpt-oss-120b модели через OpenRouter. То есть мы не использовали ни frontier-модель, ни специализированный research-agent. Базовая open-weight LLM оказалась способна поддерживать полноценный interpretability workflow поверх tabular ML.

Во-вторых, orchestration layer влияет на качество интерпретации не меньше, чем сами XAI-методы.

  • naive-agent оказался простым, рабочим, но довольно уверенным;

  • manual pipeline — последовательным и сухим, но съел часть автоматизации;

  • multi-agent pipeline — более широким и осторожным, но местами водянистым.

Critic-agent действительно улучшал отчет: чаще поднимал вопросы collinearity, calibration, leakage и limits of interpretation. Но одновременно видно, что агент очень легко начинает достраивать лишнее, а больше не всегда значит лучше. Это хорошо видно в эксперименте с batch artifact: проблему заметили все pipeline, но самый сложный pipeline не обязательно оказался самым лаконичным.

Ограничения и зачем нам надо было посмотреть математическое определение

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

Отсюда важно:

  1. корректно и аккуратно планировать tools для XAI-системы;

  2. выбирать хороший backbone агента;

  3. аккуратно проектировать состояние системы;

  4. направлять reasoning loop.

Ну и суммарно — построить агента, который объясняет модель, не очень сложно. Сложнее построить агента, который понимает, когда его объяснению нельзя доверять. И не дай бог захотеть объяснить, почему агент вызвал ту или иную тулу =)

Спасибо за чтение и ваше время, друзья! Другие туториалы публикую в блоге: https://t.me/jdata\_blog и на гитхаб: https://github.com/SadSabrina/XAI-open_materials/tree/main!

Удачи и агентов, которые не отказываются работать за меня и вас,
Ваш Дата-автор!