Image

От данных к историям: агенты кода для повествований о KPI

Фреймворк Smolagents от HuggingFace в действии

Делиться

a4ab6d3dececa1a6325480076822fb2c

Как аналитики продуктов, мы часто должны исследовать, что происходит с KPI: реагируем ли мы на аномалии на наших панелях мониторинга или просто регулярно обновляем цифры. Основываясь на своем многолетнем опыте работы аналитиком KPI, я бы оценил, что более 80% этих задач являются довольно стандартными и могут быть решены, просто следуя простому контрольному списку.

Ниже представлен высокоуровневый план расследования изменения KPI (более подробную информацию можно найти в статье «Анализ первопричин аномалий»):

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

Поскольку у нас есть четкий план выполнения, такие задачи потенциально могут быть автоматизированы с помощью агентов ИИ. Кодовые агенты, о которых мы недавно говорили, могли бы хорошо подойти, поскольку их способность писать и выполнять код поможет им эффективно анализировать данные с минимальными перемещениями туда-сюда. Итак, давайте попробуем создать такого агента с помощью фреймворка HuggingFace smolagents.

Работая над нашей задачей, мы обсудим более продвинутые возможности фреймворка smolagents:

  • Методы настройки всех видов подсказок для обеспечения желаемого поведения.
  • Создание многоагентной системы, способной объяснить изменения KPI и связать их с первопричинами.
  • Добавление размышлений в процесс с дополнительными этапами планирования.

MVP для объяснения изменений KPI

Как обычно, мы воспользуемся итеративным подходом и начнем с простого MVP, сосредоточившись на этапе срезки и разрезания анализа. Мы проанализируем изменения простой метрики (доход), разделенной на одно измерение (страна). Мы будем использовать набор данных из моей предыдущей статьи «Понимание изменений KPI».

Давайте сначала загрузим данные.

raw_df = pd.read_csv('absolute_metrics_example.csv', sep = 't') df = raw_df.groupby('country')[['revenue_before', 'revenue_after_scenario_2']].sum() .sort_values('revenue_before', ascending = False).rename( columns = {'revenue_after_scenario_2': 'after', 'revenue_before': 'before'})

eefc87bb4a24a9d9280ddfef213c6fd8

Далее, давайте инициализируем модель. Я выбрал OpenAI GPT-4o-mini в качестве предпочтительного варианта для простых задач. Однако фреймворк smolagents поддерживает все виды моделей, поэтому вы можете использовать предпочтительную модель. Затем нам просто нужно создать агента и дать ему задачу и набор данных.

from smolagents import CodeAgent, LiteLLMModel model = LiteLLMModel(model_id=»openai/gpt-4o-mini», api_key=config['OPENAI_API_KEY']) agent = CodeAgent( model=model, tools=[], max_steps=10, additional_authorized_imports=[«pandas», «numpy», «matplotlib.*», «plotly.*»], verbosity_level=1 ) task = «»» Вот фрейм данных, показывающий доход по сегментам, сравнивающий значения до и после. Не могли бы вы помочь мне понять изменения? В частности: 1. Оцените, как изменились общий доход и доход по каждому сегменту, как в абсолютном выражении, так и в процентах. 2. Рассчитайте вклад каждого сегмента в общее изменение дохода. Пожалуйста, округлите все числа с плавающей точкой в выводе до двух знаков после запятой. «»» agent.run( task, additional_args={«data»: дф}, )

Агент выдал вполне правдоподобный результат. Мы получили подробную статистику по изменению метрик в каждом сегменте и их влиянию на общий KPI.

{'total_before': 1731985.21, 'total_after': 1599065.55, 'total_change': -132919.66, 'segment_changes': {'absolute_change': {'other': 4233.09, 'UK': -4376.25, 'France': -132847.57, 'Germany': -690.99, 'Italy': 979.15, 'Spain': -217.09}, 'percentage_change': {'other': 0.67, 'UK': -0.91, 'France': -55.19, 'Germany': -0.43, 'Italy': 0.81, 'Испания': -0,23}, 'contribution_to_change': {'other': -3,18, 'Великобритания': 3,29, 'Франция': 99,95, 'Германия': 0,52, 'Италия': -0,74, 'Испания': 0,16}}}

Давайте взглянем на код, сгенерированный агентом. Он в порядке, но есть одна потенциальная проблема. Llm воссоздал фрейм данных на основе входных данных вместо того, чтобы ссылаться на него напрямую. Этот подход не идеален (особенно при работе с большими наборами данных), так как он может привести к ошибкам и более высокому использованию токенов.

import pandas as pd # Создание DataFrame из предоставленных данных data = { 'before': [632767.39, 481409.27, 240704.63, 160469.75, 120352.31, 96281.86], 'after': [637000.48, 477033.02, 107857.06, 159778.76, 121331.46, 96064.77] } index = ['other', 'UK', 'France', 'Germany', 'Italy', 'Spain'] df = pd.DataFrame(data, index=index) # Расчет общего дохода до и после total_before = df['before'].sum() total_after = df['after'].sum() # Расчет абсолютного и процентного изменения для каждого сегмента df['absolute_change'] = df['after'] — df['before'] df['percentage_change'] = (df['absolute_change'] / df['before']) * 100 # Расчет изменения общего дохода total_change = total_after — total_before # Расчет вклада каждого сегмента в общее изменение df['contribution_to_change'] = (df['absolute_change'] / total_change) * 100 # Округление результатов df = df.round(2) # Печать рассчитанных результатов print(«Общий доход до:», total_before) print(«Общий доход после:», total_after) print(«Общее изменение дохода:», total_change) print(df)

Стоит решить эту проблему, прежде чем переходить к созданию более сложной системы.

Подсказки по настройке

Поскольку LLM просто следует данным ему инструкциям, мы решим эту проблему, изменив подсказку.

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

task = «»»Вот фрейм данных, показывающий доход по сегментам, сравнивающий значения до и после. Данные хранятся в переменной df. Пожалуйста, используйте ее и не пытайтесь анализировать данные самостоятельно. Не могли бы вы помочь мне понять изменения? А именно: 1. Оцените, как изменились общий доход и доход по каждому сегменту, как в абсолютном выражении, так и в процентах. 2. Рассчитайте вклад каждого сегмента в общее изменение дохода. Пожалуйста, округлите все числа с плавающей точкой в выводе до двух знаков после запятой. «»»

Это не сработало. Поэтому следующим шагом будет изучение системного приглашения и выяснение, почему оно работает таким образом.

print(agent.prompt_templates['system_prompt']) #… # Вот правила, которым вы всегда должны следовать, чтобы решить свою задачу: # 1. Всегда предоставляйте последовательность 'Thought:' и последовательность 'Code:n«`py', заканчивающуюся последовательностью '«`', иначе вы потерпите неудачу. # 2. Используйте только те переменные, которые вы определили. # 3. Всегда используйте правильные аргументы для инструментов. НЕ передавайте аргументы как словарь, как в 'answer = wiki({'query': «What is the place where James Bond lives?»})', а используйте аргументы напрямую, как в 'answer = wiki(query=»What is the place where James Bond lives?»)'. # 4. Будьте осторожны, чтобы не сцеплять слишком много последовательных вызовов инструментов в одном блоке кода, особенно когда формат вывода непредсказуем. Например, вызов search имеет непредсказуемый формат возврата, поэтому не создавайте другой вызов инструмента, который зависит от его вывода в том же блоке: вместо этого выводите результаты с помощью print(), чтобы использовать их в следующем блоке. # 5. Вызывайте инструмент только при необходимости и никогда не повторяйте вызов инструмента, который вы уже делали с теми же параметрами. # 6. Не называйте никакую новую переменную тем же именем, что и инструмент: например, не называйте переменную «final_answer». # 7. Никогда не создавайте никаких условных переменных в нашем коде, так как наличие их в ваших журналах отвлечет вас от настоящих переменных. # 8. Вы можете использовать импорты в своем коде, но только из следующего списка модулей: ['collections', 'datetime', 'itertools', 'math', 'numpy', 'pandas', 'queue', 'random', 're', 'stat', 'statistics', 'time', 'unicodedata'] # 9. Состояние сохраняется между выполнениями кода: поэтому, если на одном шаге вы создали переменные или импортировали модули, все они сохранятся. # 10. Не сдавайтесь! Вы отвечаете за решение задачи, а не за предоставление указаний по ее решению. # Теперь начинайте!

В конце приглашения у нас есть инструкция «# 2. Используйте только те переменные, которые вы определили!». Это можно интерпретировать как строгое правило не использовать никакие другие переменные. Поэтому я изменил ее на «# 2. Используйте только те переменные, которые вы определили или те, которые указаны в дополнительных аргументах! Никогда не пытайтесь копировать и анализировать дополнительные аргументы».

modified_system_prompt = agent.prompt_templates['system_prompt'] .replace( '2. Используйте только те переменные, которые вы определили!', '2. Используйте только те переменные, которые вы определили или которые предоставлены в дополнительных аргументах! Никогда не пытайтесь копировать и анализировать дополнительные аргументы.' ) agent.prompt_templates['system_prompt'] = modified_system_prompt

Это изменение само по себе тоже не помогло. Затем я изучил сообщение о задаче.

╭──────────────────────────────── Новый запуск ───────────────────────────────╮ │ │ │ Вот фреймворк данных pandas, показывающий доход по сегментам, │ │ сравнение значений до и после. │ │ Не могли бы вы помочь мне понять изменения? │ │ В частности: │ │ 1. Оцените, как изменились общий доход и доход по каждому │ │ сегменту, как в абсолютном выражении, так и в │ │ процентах. │ │ 2. Рассчитайте вклад каждого сегмента в общее │ │ изменение дохода. │ │ │ │ Округлите все числа с плавающей запятой в выходных данных до двух │ │ десятичных знаков. │ │ │ │ Вам предоставлены эти дополнительные аргументы, к которым │ │ вы можете получить доступ, используя ключи как переменные в вашем │ │ коде Python: │ │ {'df': до после │ │ страна │ │ другой 632767,39 637000,48 │ │ Великобритания 481409,27 477033,02 │ │ Франция 240704,63 107857,06 │ │ Германия 160469,75 159778,76 │ │ Италия 120352,31 121331,46 │ │ Испания 96281,86 96064,77}. │ │ │ ╰─ LiteLLMModel — openai/gpt-4o-mini ───────────────────────────╯

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

импортировать smolagents печать(smolagents.__path__)

Затем я нашел файл agents.py и изменил эту строку, включив в нее более конкретную инструкцию.

self.task += f»»» Вам предоставлены эти дополнительные аргументы, доступные как переменные с именами {«,».join(additional_args.keys())}. Вы можете получить к ним прямой доступ. Вот что они содержат (только в ознакомительных целях): {str(additional_args)}.»»»

Это был небольшой хакерский ход, но это то, что иногда случается с фреймворками LLM. Не забудьте перезагрузить пакет после этого, и все готово. Давайте проверим, работает ли он сейчас.

task = «»» Вот фрейм данных pandas, показывающий доход по сегментам, сравнивающий значения до и после. Ваша задача — понять изменения дохода (после и до) в разных сегментах и предоставить краткое изложение. Пожалуйста, выполните следующие шаги: 1. Оцените, как изменились общий доход и доход по каждому сегменту, как в абсолютном выражении, так и в процентах. 2. Рассчитайте вклад каждого сегмента в общее изменение дохода. Округлите все числа с плавающей точкой в выводе до двух десятичных знаков. «»» agent.logger.level = 1 # Понизьте уровень детализации agent.run( task, additional_args={«df»: df}, )

Ура! Проблема исправлена. Агент больше не копирует входные переменные, а вместо этого напрямую ссылается на переменную df. Вот недавно сгенерированный код.

import pandas as pd # Рассчитать общий доход до и после total_before = df['before'].sum() total_after = df['after'].sum() total_change = total_after — total_before percentage_change_total = (total_change / total_before * 100) if total_before != 0 else 0 # Округлить значения total_before = round(total_before, 2) total_after = round(total_after, 2) total_change = round(total_change, 2) percentage_change_total = round(percentage_change_total, 2) # Отобразить результаты print(f»Общий доход до: {total_before}») print(f»Общий доход после: {total_after}») print(f»Общее изменение: {total_change}») print(f»Процентное изменение: {percentage_change_total}%»)

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

Агент ИИ для повествований KPI

Наконец, пришло время поработать над ИИ-агентом, который поможет нам объяснить изменения KPI и создать резюме.

Наш агент будет следовать следующему плану анализа первопричин:

  • Оцените изменение основного показателя эффективности.
  • Проанализируйте метрику, чтобы понять, какие сегменты являются движущей силой изменений.
  • Просмотрите события в журнале изменений, чтобы увидеть, могут ли они объяснить изменения показателей.
  • Объедините все выводы в комплексное резюме.

После множества экспериментов и нескольких доработок я пришел к многообещающему результату. Вот основные изменения, которые я сделал (мы обсудим их подробно позже):

  • Я использовал многоагентную настройку , добавив еще одного члена команды — агента журнала изменений, который может получить доступ к журналу изменений и помочь объяснить изменения KPI.
  • Я экспериментировал с более мощными моделями , такими как gpt-4o и gpt-4.1-mini, поскольку gpt-4o-mini было недостаточно. Использование более мощных моделей не только улучшило результаты, но и значительно сократило количество шагов: с gpt-4.1-mini я получил конечный результат всего за шесть шагов, по сравнению с 14–16 шагами с gpt-4o-mini. Это говорит о том, что инвестирование в более дорогие модели может быть целесообразным для рабочих процессов агента.
  • Я предоставил агенту сложный инструмент для анализа изменений KPI для простых метрик. Инструмент выполняет все вычисления, тогда как LLM может только интерпретировать результаты. Подход к анализу изменений KPI я подробно рассмотрел в своей предыдущей статье.
  • Я переформулировал подсказку в очень четкое пошаговое руководство, чтобы помочь агенту не сбиться с пути.
  • Я добавил шаги планирования , которые побуждают агента LLM сначала продумать свой подход и пересматривать план каждые три итерации.

После всех корректировок я получил от агента следующее резюме, которое весьма неплохое.

Краткое изложение: В период с апреля 2025 года по май 2025 года общий доход резко снизился примерно на 36,03%, снизившись с 1 731 985,21 до 1 107 924,43, падение составило -624 060,78 в абсолютном выражении. Это снижение было в первую очередь обусловлено значительным сокращением доходов в сегментах «новых» клиентов во многих странах, с падением примерно на 70% в этих сегментах. Наиболее затронутые сегменты включают: — other_new: до = 233 958,42, после = 72 666,89, abs_change = -161 291,53, rel_change = -68,94%, share_before = 13,51%, impact = 25,85, impact_norm = 1,91 — UK_new: до = 128 324,22, после = 34 838,87, abs_change = -93 485,35, rel_change = -72,85%, share_before = 7,41%, impact = 14,98, impact_norm = 2,02 — France_new: до = 57 901,91, после = 17 443,06, abs_change = -40 458,85, rel_change = -69,87%, share_before=3.34%, impact=6.48, impact_norm=1.94 — Германия_новое: до=48,105.83, после=13,678.94, abs_change=-34,426.89, rel_change=-71.56%, share_before=2.78%, impact=5.52, impact_norm=1.99 — Италия_новое: до=36,941.57, после=11,615.29, abs_change=-25,326.28, rel_change=-68.56%, share_before=2.13%, impact=4.06, impact_norm=1.91 — Испания_новое: до=32,394.10, после=7,758.90, abs_change=-24,635.20, rel_change=-76.05%, share_before=1.87%, impact=3.95, impact_norm=2.11 На основе анализа журнала изменений основными причинами этой тенденции являются: 1. Введение новых средств контроля за регистрацией клиентов, реализованных 8 мая 2025 года, что сократило привлечение новых клиентов примерно на 70% для предотвращения мошенничества. 2. Забастовка почтовой службы в Великобритании, начавшаяся 5 апреля 2025 года, вызвавшая задержки доставки заказов и увеличение числа отмен, что повлияло на новый сегмент в Великобритании. 3. Повышение НДС на 2% в Испании с 22 апреля 2025 года, повлиявшее на ценообразование для новых клиентов и вызвавшее более высокий уровень отказа от корзин. Эти факторы в совокупности объясняют огромные негативные последствия, наблюдаемые в новых сегментах клиентов, и общее снижение выручки.

Агент LLM также сгенерировал ряд иллюстративных диаграмм (они были частью нашего инструмента объяснения роста). Например, эта показывает влияние в сочетании страны и зрелости.

24a1a1c3ec3355dc3d91033a1b6040c3

Результаты выглядят действительно захватывающе. Теперь давайте углубимся в фактическую реализацию, чтобы понять, как она работает под капотом.

Настройка агента с несколькими ИИ

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

@tool def get_change_log(month: str) -> str: «»» Возвращает журнал изменений (список внутренних и внешних событий, которые могли повлиять на наши KPI) за указанный месяц Args: month: month в формате %Y-%m-01, например, 2025-04-01 «»» return events_df[events_df.month == month].drop('month', axis = 1).to_dict('records') model = LiteLLMModel(model_id=»openai/gpt-4.1-mini», api_key=config['OPENAI_API_KEY']) change_log_agent = ToolCallingAgent( tools=[get_change_log], model=model, max_steps=10, name=»change_log_agent», description=»Помогает найти в журнале изменений соответствующую информацию, которая может объяснить изменения в метриках. Предоставьте агенту весь контекст для получения информации», )

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

change_log_system_prompt = ''' Вы мастер журнала изменений и помогаете другим объяснять изменения в метриках. Когда вы получаете запрос, просмотрите список событий, произошедших по месяцам, затем отфильтруйте соответствующую информацию на основе предоставленного контекста и вернитесь обратно. Расставьте приоритеты среди наиболее вероятных факторов, влияющих на KPI, и ограничьте свой ответ только ими. ''' modified_system_prompt = change_log_agent.prompt_templates['system_prompt'] + 'nnn' + change_log_system_prompt change_log_agent.prompt_templates['system_prompt'] = modified_system_prompt

Чтобы позволить основному агенту делегировать задачи агенту журнала изменений, нам просто нужно указать это в поле manage_agents.

агент = CodeAgent( модель = модель, инструменты = [calculate_simple_growth_metrics], макс_шаги = 20, дополнительные_разрешенные_импорты = [«pandas», «numpy», «matplotlib.*», «plotly.*»], уровень_детализации = 2, интервал_планирования = 3, управляемые_агенты = [change_log_agent] )

Давайте посмотрим, как это работает. Сначала мы можем рассмотреть новую системную подсказку для основного агента. Теперь она включает информацию о членах команды и инструкции о том, как попросить их о помощи.

Вы также можете давать задания членам команды. Вызов члена команды работает так же, как и вызов инструмента: просто единственный аргумент, который вы можете указать в вызове, это «задача». Учитывая, что этот член команды — настоящий человек, вы должны быть очень многословны в своей задаче, это должна быть длинная строка, предоставляющая информацию настолько подробную, насколько это необходимо. Вот список членов команды, которых вы можете вызвать: «`python def change_log_agent(«Ваш запрос идет сюда.») -> str: «»»Помогает вам найти соответствующую информацию в журнале изменений, которая может объяснить изменения в метриках. Предоставьте агенту весь контекст для получения информации»»» «`

Журнал выполнения показывает, что основной агент успешно делегировал задачу второму агенту и получил следующий ответ.

<-- Основной агент, вызывающий агента журнала изменений --> ─ Выполнение проанализированного кода: ─────────────────────────────────────────── # Запрос change_log_agent с подробным описанием задачи, подготовленным context_for_change_log = ( «Мы проанализировали изменения в доходах с апреля 2025 года по май 2025 года. Мы обнаружили значительное снижение » «в основном в сегментах зрелости «новых» по странам: Spain_new, UK_new, Germany_new, France_new, Italy_new и other_new. » «Доход упал примерно на 70% в этих сегментах, что оказывает чрезмерное негативное влияние на изменение общего дохода. » «Мы хотим узнать 1-3 наиболее вероятные причины этого значительного падения дохода в сегментах «новых» клиентов за этот период.» ) объяснение = change_log_agent(task=context_for_change_log) print(«Объяснение агента журнала изменений:») print(explanation) ───────────────────────────────────────────────────────────────────────────────────── <-- Начало выполнения агента журнала изменений --> ╭─────────────────────── Новый запуск — change_log_agent ───────────────────────╮ │ │ │ Вы полезный агент под именем 'change_log_agent'. │ │ Вам отправил эту задачу ваш менеджер. │ │ — │ │ Задача: │ │ Мы проанализировали изменения в выручке с апреля 2025 года по май 2025 года. │ │ Мы обнаружили значительное снижение, в основном, в сегментах «новых» зрелости │ │ по странам: Spain_new, UK_new, Germany_new, France_new, │ │ Italy_new и other_new. Выручка упала примерно на 70% в этих │ │ сегментах, что оказало огромное негативное влияние на изменение общей выручки │ │ . Мы хотим узнать 1-3 наиболее вероятные причины этого │ │ значительного падения выручки в сегментах «новых» клиентов в течение │ │ этого периода. │ │ — │ │ Вы помогаете своему менеджеру решить более масштабную задачу: поэтому убедитесь, что │ │ не даете однострочный ответ, а дайте как можно больше информации, чтобы дать им четкое понимание ответа. │ │ │ │ Ваш final_answer ДОЛЖЕН будет содержать эти части: │ │ ### 1. Результат задачи (короткая версия): │ │ ### 2. Результат задачи (очень подробная версия): │ │ ### 3. Дополнительный контекст (если применимо): │ │ │ │ Поместите все это в свой инструмент final_answer, все, что вы │ │ не передадите в качестве аргумента final_answer, будет потеряно. │ │ И даже если решение вашей задачи не будет успешным, пожалуйста, верните │ │ как можно больше контекста, чтобы ваш менеджер мог отреагировать │ │ на этот отзыв. │ │ │ ╰─ LiteLLMModel — openai/gpt-4.1-mini ───────────────────────────────────╯

Используя фреймворк smolagents, мы можем легко настроить простую многоагентную систему, в которой менеджер-агент координирует и делегирует задачи членам команды с определенными навыками.

Итерация по подсказке

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

task = «»» Вот фрейм данных pandas, показывающий доход по сегментам, сравнивающий значения до (апрель 2025 г.) и после (май 2025 г.). Вы старший и опытный аналитик данных. Ваша задача будет заключаться в том, чтобы понять изменения в доходе (после и до) в разных сегментах и предоставить краткое изложение. ## Следуйте плану: 1. Начните с идентификации списка измерений (столбцов в фрейме данных, которые не являются «до» и «после») 2. В фрейме данных может быть несколько измерений. Начните с высокого уровня, просматривая каждое измерение по отдельности, объедините все результаты вместе в список проанализированных сегментов (не забудьте сохранить измерение, используемое для каждого сегмента). Используйте предоставленные инструменты для анализа изменений метрик: {tools_description}. 3. Проанализируйте результаты предыдущего шага и оставьте только сегменты, которые оказывают чрезмерное влияние на изменение KPI (абсолютное значение impact_norm выше 1,25). 4. Проверьте, какие измерения присутствуют в списке значимый сегмент, если их несколько — выполните инструмент на их комбинациях и добавьте к проанализированным сегментам. Если после добавления дополнительного измерения все подсегменты показывают близкие значения different_rate и impact_norm, то мы можем исключить это разделение (даже если impact_norm выше 1,25), так как это ничего не объясняет. 5. Подведите итог выявленным вами значимым изменениям. 6. Постарайтесь объяснить, что происходит с метриками, получив информацию от change_log_agent. Пожалуйста, предоставьте агенту полный контекст (какие сегменты имеют чрезмерное влияние, каково относительное изменение и какой период мы рассматриваем). Подведите итог информации из changelog и упомяните только 1–3 наиболее вероятных причины изменения KPI (начиная с самой влиятельной). 7. Составьте комментарий из 3–5 предложений о том, что произошло на высоком уровне и почему (на основе информации, полученной из change log). Затем добавьте более подробное резюме: — Верхнее общее значение метрики до и после в удобном для восприятия формате, абсолютное и относительное изменение — список сегментов, которые существенно повлияли на метрику положительно или отрицательно, со следующими числами: значения до и после, абсолютное и относительное изменение, доля сегмента до, влияние и нормированное влияние. Упорядочите сегменты по абсолютному значению абсолютного изменения, так как оно представляет силу влияния. ## Инструкция по инструменту calculate_simple_growth_metrics: по умолчанию вы должны использовать инструмент для всего набора данных, а не для сегмента, так как он даст вам полную информацию об изменениях. Вот руководство по интерпретации выходных данных инструмента — разница — абсолютная разница между значениями после и до — разница_скорость — относительная разница (если она близка для всех сегментов, то измерение неинформативно) — влияние — доля разницы KPI, объясняемая этим сегментом — доля_сегмента_до — доля сегмента до — влияние_нормировано — влияние, нормированное на долю сегментов, нас интересуют очень высокие или очень низкие числа, так как они показывают чрезмерное влияние, практическое правило — значение impact_norm между -1,25 и 1,25 not-informative Если вы используете инструмент на подмножестве dataframe, имейте в виду, что результаты не будут применимы к полному набору данных, поэтому избегайте его использования, если вы не хотите явно посмотреть на подмножество (например, изменение во Франции). Если вы решили использовать инструмент на определенном сегменте и поделиться этими результатами в резюме, явно укажите, что мы углубляемся в определенный сегмент. «»».format(tools_description = tools_description) agent.run( task, additional_args={«df»: df}, )

Объяснить все настолько подробно было довольно сложной задачей, но это необходимо, если мы хотим получить последовательные результаты.

Планирование шагов

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

Настройка так же проста, как указание planning_interval = 3 для кода агента.

агент = CodeAgent( модель = модель, инструменты = [calculate_simple_growth_metrics], макс_шаги = 20, дополнительные_разрешенные_импорты = [«pandas», «numpy», «matplotlib.*», «plotly.*»], уровень_детализации = 2, интервал_планирования = 3, управляемые_агенты = [change_log_agent] )

Вот и все. Затем агент дает размышления, начиная с размышлений о первоначальном плане.

──────────────────────────── Первоначальный план ───────────────────────────── Вот известные мне факты и план действий, которому я буду следовать для решения поставленной задачи: «` ## 1. Опрос фактов ### 1.1. Факты, приведенные в задании. У нас есть фрейм данных pandas `df`, показывающий доход по сегментам для двух временных точек: до (апрель 2025 г.) и после (май 2025 г.). — Столбцы фрейма данных включают: — Измерения: `country`, `maturity`, `country_maturity`, `country_maturity_combined` — Метрики: `before` (доход в апреле 2025 г.), `after` (доход в мае 2025 г.) — Задача состоит в том, чтобы понять изменения в доходе (после и до) по разным сегментам. — Предоставляются основные инструкции и инструменты: — Определите все измерения, кроме до/после, для сегментации. — Проанализируйте каждое измерение независимо с помощью `calculate_simple_growth_metrics`. — Отфильтруйте сегменты с чрезмерным влиянием на изменение KPI (абсолютное нормированное влияние > 1,25). — Изучите комбинации измерений, если несколько измерений имеют значимые сегменты. — Обобщите существенные изменения и задействуйте `change_log_agent` для контекстных причин. — Предоставьте окончательное резюме, включая основные изменения и подробные воздействия на уровне сегмента. — Фрагмент набора данных показывает сегменты, объединяющие страны (`France`, `UK`, `Germany`, `Italy`, `Spain`, `other`) и статус зрелости (`new`, `existing`). — Объединенные сегменты однозначно идентифицируются в столбцах `country_maturity` и `country_maturity_combined`. ### 1.2. Факты для поиска — Определения или описания сегментов, если они неясны (например, что определяет `new` и `existing` зрелость). — Вероятно, не обязательно для продолжения, но может быть запрошено из деловой документации или журнала изменений. — Дополнительные сведения о журнале изменений (доступные через `change_log_agent`), которые могут предоставить вероятные причины изменения доходов. — Подтверждение обработки комбинированных разделений измерений — как именно формируется `country_maturity_combined` и как его следует интерпретировать в комбинированном анализе измерений. — Словарь данных или описание метрик, если какой-либо дополнительный KPI, помимо дохода, является релевантным (маловероятно, что данные приведены). — Даты подтверждают период анализа: апрель 2025 г. (до) и май 2025 г. (после). Нет необходимости искать их, поскольку они указаны. ### 1.3. Факты для вывода — Определите все столбцы измерений, доступные для сегментации: — Исключив `before` и `after`, вероятными кандидатами являются `country`, `maturity`, `country_maturity` и `country_maturity_combined`. — Для каждого измерения рассчитайте метрики изменений с помощью указанного инструмента: — Абсолютная и относительная разница в доходе на сегмент. — Влияние, доля сегмента до и нормированное влияние для каждого сегмента. — Определите, какие сегменты оказывают чрезмерное влияние на изменение KPI (|impact_norm| > 1,25). — Если несколько измерений имеют значимые сегменты, объедините измерения (например, страна + зрелость) и проанализируйте повторно. — Определите, обеспечивают ли комбинированные разделения измерений значимую дифференциацию или нет, на основе дельта-скорости и согласованности impact_norm. — Обобщите направление и величину изменений KPI на уровне верхней строки (совокупный доход до и после). — Определите основные сегменты, вызывающие положительные и отрицательные изменения, на основе упорядоченного абсолютного absolute_change. — Соберите контекстную информацию от агента журнала изменений относительно вероятных причин, связанных со значимыми сегментами и периодом май 2025 г. по сравнению с апрелем 2025 г. ## 2. План 1. Определите все столбцы измерений, присутствующие в фрейме данных, перечислив столбцы и исключив «до» и «после». 2. Для каждого идентифицированного измерения (`country`, `maturity`, `country_maturity`, `country_maturity_combined`): — Используйте `calculate_simple_growth_metrics` для полного фрейма данных, сгруппированного по этому измерению. — Извлеките сегменты с рассчитанными метриками, включая impact_norm. 3. Объедините результаты всех одномерных анализов и отфильтруйте сегменты, где |impact_norm| > 1,25. 4. Определите, к каким измерениям относятся эти значимые сегменты. 5. Если в этих значимых сегментах представлено более одного измерения, проанализируйте объединенное измерение, образованное этими измерениями (например, сочетание `country` и `maturity` или используйте существующие столбцы объединенных измерений). 6. Повторите расчет метрик, используя `calculate_simple_growth_metrics` для объединенного измерения. 7. Проверьте, создают ли объединенные разделения измерений значимую дифференциацию — если все подсегменты показывают близкие difference_rate и impact_norm, исключите разделение. 8. Подготовьте сводку значительных изменений: — Основные KPI до и после (абсолютные и относительные изменения). — Список влиятельных сегментов, отсортированных по абсолютному absolute_change, которые повлияли на общий доход. 9. Предоставьте список сегментов с подробностями (значения до, после, абсолютное и относительное изменение, доля до, влияние, impact_norm). 10. Используя эту обобщенную информацию, запросите `change_log_agent` с полным контекстом: — Включите значимые сегменты, их относительные изменения и периоды (с апреля по май 2025 г.). 11. Обработайте ответ агента, чтобы определить 1–3 основные вероятные причины изменений KPI. 12. Составьте черновой комментарий к резюме: — Общий обзор того, что произошло и почему, на основе информации журнала. — Подробное резюме, включая изменения в верхней строке и влияние метрик на уровне сегмента. 13. Предоставьте окончательный ответ с помощью инструмента `final_answer`, содержащего вышеуказанное резюме и аналитические данные на основе данных.

Затем, после каждых трех шагов, агент пересматривает и обновляет план.

────────────────────────────── Обновленный план ──────────────────────────── Мне еще нужно решить задачу, которую мне дали: «` Вот фреймворк данных pandas, показывающий доход по сегментам, сравнивающий значения до (апрель 2025 г.) и после (май 2025 г.). Вы старший и опытный аналитик данных. Ваша задача — понять изменения в доходе (после и до) в разных сегментах и предоставить краткое изложение. <... повторение полной первоначальной задачи ...> «` Вот известные мне факты и мой новый/обновленный план действий для решения задачи: «` ## 1. Обновленный опрос фактов ### 1.1. Факты, указанные в задаче. — У нас есть фрейм данных pandas с доходом по сегментам, показывающий значения «до» (апрель 2025 г.) и «после» (май 2025 г.). — Столбцы в фрейме данных включают несколько измерений и значения дохода «до» и «после». — Цель — понять изменения дохода по сегментам и предоставить краткое изложение. — Предоставляются рекомендации и правила анализа и интерпретации результатов инструмента `calculate_simple_growth_metrics`. — Фрейм данных содержит столбцы: страна, зрелость, country_maturity, country_maturity_combined, до, после. ### 1.2. Факты, которые мы узнали — Анализируемые измерения: страна, зрелость, страна_зрелость и страна_зрелость_комбинированная. — Анализ изменений выручки по измерениям. — Только сегмент «новый» зрелости имеет значительное влияние (impact_norm = 1,96 > 1,25) с большим отрицательным изменением выручки (~ -70,6%). — В объединенном сегменте «страна_зрелость» все «новые» сегменты по странам (Испания_новая, Великобритания_новая, Германия_новая, Франция_новая, Италия_новая, другие_новые) имеют чрезмерное отрицательное влияние со значениями impact_norm выше 1,9. — Зрелые/существующие сегменты в этих странах имеют меньшее нормированное влияние ниже 1,25. — Измерение сегмента на уровне страны и на уровне зрелости по отдельности менее показательно, чем объединенное измерение сегмента страна+зрелость, которое выделяет новые сегменты как оказывающие сильное влияние. — Общий доход существенно снизился по сравнению с предыдущим периодом, в основном из-за резкого сокращения новых сегментов. ### 1.3. Факты, которые еще предстоит выяснить — Объясняет ли разделение данных по дополнительным измерениям, выходящим за рамки страны и зрелости (например, country_maturity_combined), дальнейшие неоднородные воздействия или же эта закономерность является однородной. — Объяснение/контекст из журнала изменений о том, что вызвало существенное падение, в основном в новых сегментах во всех странах. — Подтверждение того, вела ли себя какая-либо страна в новом сегменте по-другому или смягчила потери. ### 1.4. Факты, которые еще предстоит выяснить — Краткое резюме, описывающее изменение выручки на верхнем уровне и определяющее, какие сегменты объясняют снижение. — Объяснение с участием агента журнала изменений с кратким изложением вероятных причин этих существенных сокращений выручки в новых сегментах по странам за апрель-май 2025 г. ## 2. План ### 2.1. Проверьте, разбивает ли добавление дополнительного измерения 'country_maturity_combined' эффективные «новые» сегменты на подсегменты с существенно разными эффектами или же темпы изменений и нормированные эффекты относительно однородны. Если они однородны, мы не получаем более глубокого понимания и должны игнорировать дальнейшее разбиение. ### 2.2. Обобщите все значимые сегменты, идентифицированные с негабаритным impact_norm ≥ 1,25, включая их значения до и после, абсолютные и относительные изменения, доли сегментов до, воздействия и нормализованного воздействия, упорядоченные по абсолютному значению изменения. ### 2.3. Запросите change_log_agent с полным контекстом: значимые сегменты — это новые сегменты country_maturity с большими отрицательными изменениями (~ -70%), временной интервал с апреля 2025 года по май 2025 года, и запросите 1–3 наиболее вероятных причины падения выручки KPI в этих сегментах. ### 2.4. На основе ответа агента журнала изменений синтезируйте комментарий высокого уровня из 3-5 предложений, объясняющий, что произошло в общих чертах и почему. ### 2.5. Составьте подробный отчет о руководстве, включая: — Общий доход до и после в удобном для чтения формате с абсолютным и относительным изменением. — Список значимых сегментов, обусловливающих эти изменения, в порядке абсолютного воздействия, с подробными цифрами (до, после, абсолютное и относительное изменение, доля сегмента до, воздействие, нормированное воздействие). ### 2.6. Используйте инструмент `final_answer` для создания окончательного отчета о руководстве.

Мне очень нравится, как агента поощряют повторять начальную задачу и оставаться сосредоточенным на главной проблеме. Регулярные размышления, подобные этому, полезны и в реальной жизни, поскольку команды часто увязают в процессе и теряют из виду причину того, что они делают. Довольно здорово видеть, как лучшие управленческие практики интегрируются в агентские фреймворки.

Вот и все! Мы создали код-агент, способный анализировать изменения KPI для простых метрик, и изучили все ключевые нюансы процесса.

Полный код и логи выполнения можно найти на GitHub.

Краткое содержание

Мы много экспериментировали с агентами кода и теперь готовы сделать выводы. Для наших экспериментов мы использовали фреймворк HuggingFace smolagents для агентов кода — очень удобный набор инструментов, который предлагает:

  • простая интеграция с различными LLM (от локальных моделей через Ollama до публичных поставщиков, таких как Anthropic или OpenAI),
  • превосходное ведение журнала, которое позволяет легко понять весь мыслительный процесс агента и устранять неполадки,
  • способность создавать сложные системы, использующие настройки нескольких агентов ИИ или функции планирования без особых усилий.

Хотя на данный момент smolagents является моим любимым агентским фреймворком, у него есть свои ограничения:

  • Иногда ему не хватает гибкости. Например, мне пришлось изменить подсказку прямо в исходном коде, чтобы получить желаемое поведение.
  • Он поддерживает только иерархическую многоагентную настройку (где один менеджер может делегировать задачи другим агентам), но не охватывает последовательный рабочий процесс или процессы принятия решений на основе консенсуса.
  • В стандартной комплектации поддержка долговременной памяти отсутствует, поэтому каждую задачу вам придется начинать с нуля.

Большое спасибо за прочтение этой статьи. Надеюсь, эта статья была для вас познавательной.

Ссылка

Эта статья написана по мотивам краткого курса «Агенты строительного кода с обнимающимися лицами» от DeepLearning.AI.

Источник: towardsdatascience.com

❌ Нет тегов для этой статьи
Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых