AAYMA
RU
Войти

Flora

Статистический агент для Beeline, который выбирает сегменты, целевые тарифы и каналы (push, SMS, digital_ads), проводит последовательные пилоты и…

Доведённый продукт
Команда «Flora» 23💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Flora
Кейс HackAlem.ai: Телеком — Beeline
Стадия: Доведённый продукт

Задача кейса: Агент, который решает, каким абонентам какой тариф предложить (чистый прирост ARPU)

Суть

Статистический агент для Beeline, который выбирает сегменты, целевые тарифы и каналы (push, SMS, digital_ads), проводит последовательные пилоты и распределяет бюджет между до 10 кампаниями ради чистого прироста ARPU; Streamlit-панель с опциональным AI-ассистентом.

Как устроено

История переходов тарифов задаёт априорные оценки по сегментам ARPU; коррелированная модель θ = β0 + β1·m0 + u с эмпирическим Байесом калибруется по шумным пилотам. Следующий пилот выбирается по Knowledge Gradient (ожидаемая польза информации для итогового плана). Финальный план: MILP (scipy.optimize.milp/HiGHS) по целым ячейкам аудитории с ограничениями бюджета 100 000, 15 000 контактов и 5 000 на кампанию, отбор по нижней границе mean − z·sd, запасной жадный планировщик. LLM не участвует в решениях, только в чате-объяснении плана.

Ключевые решения

  • Knowledge Gradient
  • коррелированные нормальные убеждения
  • эмпирический Байес
  • MILP (HiGHS)
  • нижняя доверительная граница
  • жадный fallback
  • стресс-стенд с LP-оракулом

Метрики

seed 42: +5 957 337 против −1 035 279 у шаблона; 10/10 seed в плюсе, медиана +5 616 633; стресс-стенд 75/75 в плюсе, 79% от ЛП-оракула; реалистичный стенд: минус в 1 из 54

Особенности

Строгий подход optimal learning (Knowledge Gradient по Frazier/Powell) вместо LLM-агента, плюс проверка на стресс-стендах, где эффекты расходятся с историей, и сравнение с LP-оракулом; отклонённые эксперименты задокументированы.

Стек

Python · SciPy · Streamlit


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-9e1c0a41-flora.

README

README.md

Flora: агент тарифных маркетинговых кампаний

Кейс 04 Beeline, HackAlem AI. Flora помогает аналитику маркетинга выбрать сегменты, целевые тарифы и каналы коммуникации при неизвестном поведении аудитории. Агент проверяет гипотезы пилотами и распределяет оставшиеся ресурсы между кампаниями. Демо и расчёты работают локально, без API-ключей. Финальная версия алгоритма: v5, логика зафиксирована в коммите e1a62ee; исправления запасного планировщика и текста объяснения без изменения основного пути — ad32b4e (регрессионные тесты в tests/).

Быстрая проверка

Из корня репозитория, Python 3.10+:

pip install -r requirements.txt
python local_eval.py
python make_submission.py
python tests/test_agent_regressions.py

Ожидается для v5, seed 42: +5 957 337, 20 пилотов, 10 финальных кампаний. Тесты: «Все тесты пройдены: 4».

Результат коротко

ПроверкаШаблон организаторовFlora v5
Мок-среда, seed 42 (python local_eval.py)−1 035 279+5 957 337
Мок-среда, seed 0–9 (python local_eval.py --runs 10)0 из 10 в плюсе, медиана −357 94810 из 10 в плюсе, медиана +5 616 633
Стресс-стенд, 15 сценариев × 5 seed (python stress_eval.py --template)медиана в минусе в 12 из 15 сценариев75 из 75 в плюсе, 79 % от ЛП-оракула, худший +0,74 млн
Реалистичный стенд, 2 набора × 27 прогонов (tools/realistic_bench.py)—в минусе 1 из 54, худший −0,22 млн

Данные кейса синтетические; мок построен из той же истории, что и исходная оценка агента, поэтому главная проверка — стенды, где эффекты расходятся с историей. Подробности, версии и размеры проверок — в разделе Результаты и стресс-стенд и в docs/RESULTS.md.

Содержание

Проблема и пользователь

Не каждый переход увеличивает выручку: возможны снижение ARPU, низкая конверсия и расходы на контакты. История описывает другую аудиторию, а малые пилоты шумят. Аналитику нужно решить не только «кому предложить тариф», но и «что проверить следующим». Цель: чистый прирост ARPU по уникальным абонентам минус стоимость всех контактов, включая пилоты. Это результат симуляции в условных единицах, не прогноз прибыли Beeline.

Что реализовано

  • Agent.act(env): исходные оценки по истории, последовательные пилоты и обновление модели.
  • Knowledge Gradient, коррелированные убеждения и эмпирическая калибровка неопределённости.
  • MILP-планировщик целых ячеек с ограничениями ресурсов и запасным жадным отбором.
  • Выбор push, SMS и digital_ads; бюджет 100 000 у.е., до 15 000 контактов, 20 пилотов, 1–10 финальных кампаний и до 5 000 абонентов на кампанию.
  • Журнал trace, таблица plan_table и локальное текстовое explanation.
  • Streamlit-панель: сравнение с шаблоном на том же seed, пилоты, отказы, план с причинами, кэшируемая серия 0–9 и опубликованный стресс-отчёт.
  • Две темы панели: нежная ботаническая Flora и строгая Beeline. Переключение оформления не меняет расчёт или план; изображения включены в репозиторий.
  • Портрет сегмента выбранной кампании: состав по потреблению данных и звонков, число абонентов, текущий и прогнозный ARPU. Это описание, не дополнительный отбор.
  • Необязательный ассистент по готовому плану, только в панели: кнопка «Спросить AI» в боковой панели открывает компактное окно чата в правом нижнем углу (сворачивается, история сохраняется), а также форма в разделе «Объяснение». Без ключа или при ошибке API показывает локальное объяснение с пометкой; решения агента не меняет. Ответы только по теме кейса, с проверкой чисел по данным плана.
  • Генерация submission.csv организаторским скриптом.

Соответствие ТЗ

Карта проверки по руководству участников, разделы 7–9. Слово «частично» обозначает ограничение реализации, а не полностью выполненный пункт.

Требование ТЗГде реализованоКак проверить
Must-have 1: Agent.act(env) без ошибокagent.py, класс Agentpython local_eval.py: итоговый отчёт без «Агент упал»
Must-have 2: 1–10 корректных кампаний_plan, _plan_milp, запасной отборpython make_submission.py: 1–10 строк; в оценке нет «Кампания … отброшена»
Must-have 3: решения на основе пилотов_explore, _posterior, Knowledge GradientПилотов больше нуля; раздел «Решения» показывает наблюдения и пересчёт оценок
Must-have 4: бюджет, охват, число пилотовMILP-ограничения и учёт оставшихся ресурсовpython local_eval.py: до 100 000 у.е., 15 000 контактов и 20 пилотов
Must-have 5: воспроизводимый CSVmake_submission.py, submission.csvПовторить генератор на том же коммите и сравнить содержимое с закоммиченным файлом
Учёт неопределённости_posterior, _options, нижние оценкиРазделы «Решения» и «План»: оценка до/после и нижняя граница
Адаптивная разведка: частичноПоследовательный выбор гипотез и остановка; размер обычно 200Журнал пилотов; отдельной оптимизации размера пилота нет
Осмысленный выбор канала_options, MILPРаздел «План»: push, SMS, digital_ads и обоснования
Устойчивостьlocal_eval.py, stress_eval.pypython local_eval.py --runs 10, python stress_eval.py --template
LLM в принятии решений: не реализованоДетерминированный статистический агент; LLM только для объяснений в панелиВ act() нет API-вызовов; опциональный ассистент в разделе «Объяснение» не меняет план
«Кого»: ARPU и тариф; data/call описательноФильтры плана; app.py, портрет сегментаВыбрать кампанию в разделе «План»; потребление не используется как новый критерий отбора
«Что»: предложения из истории_prior, _candidatesСписок целевых тарифов плана; переходы вне истории не исследуются
«Как»: три канала из четырёхFINAL_CHANNELS, _optionscall исключён осознанно, см. «Проектные решения»

Как работает

  1. Публичная история задаёт исходные оценки переходов между тарифами для сегментов ARPU.
  2. Агент выбирает пилот по ожидаемой пользе информации для итогового плана.
  3. env.run_pilot возвращает шумное наблюдение и списывает контакты и бюджет.
  4. Агент уточняет модель, отбирает кампании и выбирает каналы.
  5. Скорер считает эффект, стоимость, обрезку охвата и дедупликацию. Пилоты также идут в зачёт.

Агентность здесь означает цикл «наблюдение → обновление убеждений → выбор следующего действия». Это статистическое последовательное обучение, а не LLM-агент.

Метод

Оптимальное обучение / Knowledge Gradient. Пилот оценивается через ожидаемое улучшение решения после наблюдения. Основа: Peter Frazier, Warren Powell и Savas Dayanik, The Knowledge-Gradient Policy for Correlated Normal Beliefs (2009). Командная реализация адаптирует этот принцип к ценности плана и использует численное интегрирование. Это не доказательство глобальной оптимальности при всех лимитах кейса.

Коррелированные убеждения. Модель θ = β0 + β1 · m0 + u калибрует историю m0 общими параметрами: пилот по одной гипотезе уточняет и другие. Индивидуальная часть u допускает отклонения конкретного перехода от общей зависимости.

Эмпирический Байес. Масштабы неопределённости переноса истории оцениваются по правдоподобию пилотов: постоянная часть и часть, связанная с конверсией. Принцип оценивания априорных параметров по данным описан, в частности, Bradley Efron в Empirical Bayes Estimates for Large-Scale Prediction Problems. Код реализован командой; готовые реализации из этих работ не копировались.

Отбор и правило риска v5. Основной набор кандидатов проходит проверку mean - z * sd: z = 0.5 для связок, проверенных пилотом, и z = 1.0 для непроверенных. Если хотя бы один из двух масштабов эмпирического Байеса достигает 1.5, порог для непроверенных связок повышается до z = 1.5. В обычном режиме остаток контактов может идти в бесплатный push по положительной средней оценке; при ненадёжной истории этот дополнительный этап отключается. Нижняя оценка является правилом модели, а не гарантией отсутствия убытков.

MILP-планировщик. scipy.optimize.milp / HiGHS выбирает целые ячейки аудитории с учётом контактов, бюджета, до 10 кампаний и до 5 000 абонентов на кампанию. Ценность кандидатов задаётся моделью агента. Это оптимизация сформированного набора кандидатов, а не всех возможных стратегий обучения. При недоступности SciPy или ошибке оптимизатора используется запасной жадный отбор.

Проектные решения

  • Каналы: push, SMS и digital_ads. Дорогой call исключён из набора кандидатов; в проверке на данных кейса при исчерпанном бюджете digital_ads давал больше дополнительного эффекта на единицу затрат. Перенос SMS-оценки на звонок также может завышать эффект из-за потолка конверсии. Это выбор реализации, а не утверждение о превосходстве рекламы над звонками для любой аудитории.
  • Основные фильтры: текущий тариф и ARPU-сегмент. В публичной механике эффект задаётся этой парой и предложением; сегменты данных и звонков меняют состав аудитории.
  • Пилоты обычно используют до 200 абонентов. При публичном шуме 0.804 / sqrt(n) большее фактическое n уменьшает неопределённость. Выбор гипотез и остановка разведки адаптивны; размер пилота не оптимизируется отдельным поиском.
  • LLM не участвует в решениях: воспроизводимость плана и submission.csv важнее недетерминированной генерации. Объяснение составляется локально из журнала.
  • data/traffic.csv и data/arpu_monthly.csv не читаются агентом: прогнозный predicted_arpu уже входит в профиль, а эффект в публичной модели не зависит от трафика.

Технологии и архитектура

Python 3.10+, pandas, NumPy; SciPy для MILP-планировщика и ЛП-оракула стресс-стенда; Streamlit для демо. LLM и внешние API не участвуют в принятии решений при запуске.

flowchart TD
    H["История смен тарифов<br/>data/change_tariff.csv"] --> P["Априорная оценка связок<br/>(тариф × ARPU-сегмент) → тариф"]
    A["Аудитория и лимиты<br/>env.customer_profile, env.channels"] --> P
    P --> B["Совместная гауссова модель<br/>θ = β0 + β1·m0 + u"]
    B --> K{"Knowledge Gradient:<br/>какой пилот полезнее всего?"}
    K -->|пилот| E["env.run_pilot<br/>шумное наблюдение"]
    E --> U["Байесовское обновление<br/>+ эмпирический Байес: доверие к истории"]
    U --> K
    K -->|польза исчерпана или 20 пилотов| R["Правило риска v5<br/>нижняя граница, порог по состоянию модели"]
    R --> M["MILP-планировщик scipy / HiGHS<br/>бюджет, контакты, до 10 кампаний, до 5 000 абонентов"]
    M -->|ошибка солвера| G["Запасной жадный отбор"]
    M --> O["1–10 кампаний<br/>+ trace, plan_table, explanation"]
    G --> O
    O --> S["scoring_core.py · local_eval.py<br/>make_submission.py → submission.csv"]
    O --> UI["app.py — панель аналитика"]

agent.py, stress_eval.py, app.py относятся к командному решению. Панели также необходимы ui_i18n.py и каталог assets/; они поставляются вместе с app.py. Среда, скорер, генератор submission и шаблон предоставлены организаторами.

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

ПутьАвторНазначение
agent.pyкомандаагент: class Agent, act(env)
tests/test_agent_regressions.pyкомандарегрессионные тесты агента
stress_eval.pyкомандастресс-стенд: 15 сценариев эффектов + ЛП-оракул
tools/compare_versions.py, tools/no_exploration_check.pyкомандасравнение версий, калибровка стенда по подсказке ТЗ
tools/realistic_bench.pyнезависимый ревьюер командыреалистичный стенд: миры, слабо связанные с историей
app.py, ui_i18n.py, assets/командаStreamlit-панель (RU/KK/EN), изображения оформления
docs/RESULTS.mdкомандавсе опубликованные числа с версиями и размерами проверок
docs/PLAN.md, docs/CHATGPT_PROMPT.mdкомандаисторические рабочие материалы 13:40, не описывают финальную версию
requirements.txt, requirements-app.txt, .env.exampleкомандазависимости агента / панели, пример окружения
submission.csvгенерируетсяpython make_submission.py, seed 42
environment.py, mock_environment.py, scoring_core.py, local_eval.py, make_submission.py, agent_template.pyорганизаторысреда, скорер, проверка, шаблон — без изменений
customer_profile.csv, data/*.csv, *_dictionary.csv, docs/PARTICIPANT_GUIDE.mdорганизаторысинтетические данные и ТЗ кейса

Установка

Нужен Python 3.10 или новее. Команды выполняются из корня репозитория. Финальная v5 проверена в чистом клоне с GitHub и новом venv на Python 3.10.8 (23.09.2026 15:55, коммит 311ccc0) и на Python 3.12.14. Версия и размер каждой серии указаны ниже. Интернет нужен для первоначальной установки библиотек. После установки основной сценарий работает без сети и без учётных записей.

Windows PowerShell:

python -m venv .venv
.\.venv\Scripts\Activate.ps1
$env:PYTHONIOENCODING = "utf-8"
python -m pip install -r requirements.txt

Для Windows Launcher также подходит py -3 -m venv .venv. Если активация заблокирована PowerShell, запускайте .\.venv\Scripts\python.exe вместо python. В cmd.exe настройка кодировки: set PYTHONIOENCODING=utf-8.

Linux/macOS:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

Для панели дополнительно установите её зависимости (в том же окружении):

python -m pip install -r requirements-app.txt

Этот файл включает основные зависимости и streamlit>=1.49,<2. Проверенный набор версий (чистые клоны 23.09.2026): Python 3.10.8, pandas 2.3.3, numpy 2.2.6, scipy 1.15.3, streamlit 1.64.0; также Python 3.12.14. Протокол финальных проверок — docs/VERIFICATION.md. SciPy используется агентом для MILP; без него агент переходит на жадный отбор. Оракулу стресс-стенда SciPy необходим.

Обязательных переменных окружения нет; для агента и офлайн-демо OPENAI_API_KEY не нужен. Необязательная FLORA_RESULTS_PATH указывает на локальный RESULTS.md. По умолчанию панель читает docs/RESULTS.md внутри репозитория. Отсутствие отчёта не мешает расчётам и показывается явно.

Необязательный ассистент панели

В разделе «Объяснение» доступен вопрос по готовому плану. По умолчанию режим локальный: возвращается сохранённое объяснение агента, без генерации LLM. В форме раздела «Объяснение» внешний запрос возможен только после включения LLM · OpenAI и отправки вопроса. Плавающий чат «Спросить AI» при наличии ключа сразу работает через OpenAI (режим подписан в окне); запрос уходит только при нажатии «Спросить», при открытии окна запросов нет. Ключ берётся из OPENAI_API_KEY в окружении процесса или из файла .env в корне проекта (формат как в .env.example; файл в .gitignore, уже заданные переменные окружения имеют приоритет), модель — из OPENAI_MODEL (по умолчанию gpt-4.1-mini). Агент .env не читает.

Защита от ответов не по теме и выдуманных фактов:

  • ответ в строгой JSON-схеме: модель отмечает, относится ли вопрос к плану и кейсу 04 и есть ли ответ в данных; вопрос не по теме (другие темы, смена роли, «игнорируй инструкции») получает отказ; модель помечает тему сама, поэтому точная форма отказа не гарантирована (в проверке 17:11–17:16 такие запросы не выполнялись);
  • в контекст передаются факты и границы кейса: что оптимизирует агент и чего модель не знает (выгода и отток абонентов, реальные данные Beeline); temperature = 0;
  • вопросы именно о выгоде абонента не отправляются в LLM: панель отвечает фиксированным фактом о модели (выгода абонента не моделируется) — модель склонна додумывать здесь даже при явном запрете; вопросы о каналах и кампаниях этот фильтр не перехватывает;
  • эвристическая проверка чисел: каждое число ответа должно совпасть с каким-либо значением из переданных данных с точностью своей записи («5 957 337» — до целого, «5,96 млн» — до указанных знаков); привязки к конкретной метрике нет, поэтому это снижение риска, а не гарантия; при неподтверждённом числе показывается локальное объяснение. Производные числа, которых нет в данных (например, самостоятельно посчитанные суммы), тоже отклоняются;

Используется OpenAI Responses API, через стандартную библиотеку Python: дополнительные пакеты не нужны. Передаются вопрос, агрегированные метрики, до 10 кампаний и до 50 записей журнала, без строк клиентского профиля. Нужны сеть, доступная модель и лимит API. Один запрос по кнопке, тайм-аут 20 секунд, без автоматических повторов, store=false. Отсутствие ключа, ошибка сети или API не прерывает демо: показывается локальный текст. store=false не означает отсутствия всех служебных журналов у провайдера.

Ассистент не вызывает Agent.act, не запускает кампании, не пишет CSV и может ошибаться в объяснении. Его нельзя считать выполнением опционального пункта «LLM в контуре принятия решений». Обработка ответов и отказов проверена с подставными HTTP-ответами, а 23.09.2026 в 17:11–17:16 — реальными запросами к OpenAI (ложные «99 млн», гарантии, отток, «реальное внедрение», смена роли): выдуманные показатели не подтверждены.

Запуск

python local_eval.py
python local_eval.py --runs 10
python make_submission.py
python stress_eval.py
python stress_eval.py --template
streamlit run app.py

Если streamlit не найден, используйте python -m streamlit run app.py. local_eval.py занимает несколько секунд; десять прогонов дольше примерно в десять раз. Полный стресс-стенд с шаблоном может занять несколько минут. Время зависит от машины и версии решателя.

Деплой

Локальное демо: localhost:8501. Публичного размещения нет. В закрытой сети можно отключить телеметрию: streamlit run app.py --browser.gatherUsageStats=false.

Проверка за 5 минут

После установки зависимостей:

  1. python local_eval.py: без сообщений «Агент упал» и отброшенных кампаний; пилотов больше нуля, затраты не выше 100 000, контакты не выше 15 000.
  2. python make_submission.py: CSV с 1–10 финальными кампаниями. Повтор генератора с тем же кодом и окружением должен воспроизвести файл. Общее число кампаний в local_eval.py включает пилоты и может быть больше 10.
  3. streamlit run app.py: seed 42, кнопка «Рассчитать кампании». Появляются результаты обоих агентов, пилоты, план и объяснение. Смена раздела или темы не запускает расчёт заново.
  4. В разделе «Устойчивость» нажать «Проверить seed 0–9»: числа вычисляются на месте, повтор использует кэш, привязанный к коду и данным.

Ожидаемый результат финальной v5, мок, seed 42: Flora +5 957 337, шаблон −1 035 279, 20 пилотов и 10 финальных кампаний. Панель показывает вычисленный результат; опубликованное число не подставляется. Проверка v5 в чистой копии с новым venv, Python 3.12.14 и установкой requirements-app.txt: команды оценки и генерации CSV выполнены, серия seed 0–9 совпала с таблицей ниже, SHA256 исходного и повторно созданного CSV совпали. Streamlit AppTest проверил seed 42, пять разделов с сохранением расчёта, показ финального отчёта v5 и локальный ответ при отсутствии API-ключа. Запуск python -m streamlit run app.py --server.headless true проверен: страница и проверка состояния сервера возвращают HTTP 200. Отдельно v5 проверена в чистом клоне с GitHub на Python 3.10.8 (requirements.txt): local_eval.py +5 957 337, --runs 10 10/10, submission.csv совпал байт в байт, stress_eval.py и tools/*.py запускаются. Фаззинг по 21 искажённой среде (другие выборки, лимиты, каналы, неизвестные тарифы, NaN) падений не выявил; submission.csv одинаков при разных PYTHONHASHSEED.

Результаты и стресс-стенд

Источник статичных чисел: docs/RESULTS.md, раздел «Итог финальной версии v5 на стресс-стенде», прогон 23.09.2026 15:40. Это результаты на синтетических данных кейса, не обещание балла на скрытой модели.

ПроверкаРезультат v5
Мок, seed 42+5 957 337
Мок, seed 0–910/10 в плюсе
Медиана / минимум мока, seed 0–9+5 616 633 / +4 898 623
Стресс, 15 сценариев × 5 seed (0–4)75/75 в плюсе
Медиана / минимум этих 75 стресс-прогонов+5,94 / +0,74 млн
Медиана эффективности по этим 15 сценариям79% от ЛП-верхней границы
Максимальное время act() в этих 75 прогонах3,0 с

На реалистичном стенде tools/realistic_bench.py проверено 9 миров × 3 seed = 27 прогонов на каждый набор реализаций. Для набора 300 переход v4 → v5 улучшил худший результат с −2,24 до −0,22 млн, среднее с 11,98 до 12,24 млн (около +2%). Для набора 100 среднее выросло с 15,90 до 16,06 млн (около +1%). Выборка мала, улучшение худшего случая связано с одним миром; убыточные прогоны сохраняются. Эти результаты не смешиваются с серией 75/75 на другом стенде.

Сценарии меняют эффекты и конверсию: сдвиг среднего, перестановки, смена знаков, тяжёлые хвосты, слабая связь с историей и другие выборки истории. Оракул знает эффекты и решает линейную релаксацию распределения ресурсов в агрегированной модели (ячейка как единое целое, средний ARPU). Это ЛП-ориентир для данных кейса, а не глобальный теоретический максимум любой допустимой стратегии: ограничение числа кампаний ослаблено, разбиение крупных ячеек не моделируется.

Формулировки «пилот на 30 клиентах ошибается примерно в каждом четвёртом случае» и «без разведки примерно в 15 раз меньше» относятся к ТЗ организаторов (руководство участников, раздел 4), а не к нашим замерам. Подсказка ТЗ про стратегию без разведки служит ориентиром для калибровки сценариев. По отчёту команды план по истории без пилотов даёт около 1/15–1/26 результата оракула в сценариях со слабой связью с историей. Предположение, что этот класс ближе к судейской среде, остаётся рабочей гипотезой. Скрытая модель неизвестна. Шаблон организаторов сам проводит пилоты и не является стратегией «без разведки».

Данные и интеграции

Используются локальные синтетические данные организаторов Beeline: customer_profile.csv, data/change_tariff.csv, data/dict_tariff.csv и справочники. Агент получает аудиторию и параметры через публичную среду, читает разрешённую историю и узнаёт целевые эффекты только из пилотов. К внутренностям среды и скрытой модели агент не обращается. Панель не отправляет настоящие SMS, push, звонки и рекламные кампании.

Ограничения

  • Мок и исходная оценка используют одну историю; успех на моке не доказывает перенос.
  • Пилоты шумные и расходуют ресурсы. Прибыль не гарантирована даже при положительной нижней оценке. Сильный сдвиг эффектов может дать убыток.
  • Выбор пилотов и распределение ресурсов не являются точным глобальным оптимумом.
  • MILP проверяет ёмкость группы кампаний суммарно (≤ 5 000 × число кампаний), а упаковка целых ячеек идёт после; в редких сочетаниях размеров ячеек упаковке нужно больше кампаний, чем учёл оптимизатор, и лишние наименее ценные группы отбрасываются (лимит 10 кампаний при этом соблюдается).
  • При доступной истории гипотезы строятся по встречавшимся переходам, затем оставляется ограниченное число предложений на ячейку. На текущих данных не все комбинации тарифов исследуются.
  • Размер пилота обычно 200; на малой ячейке используется доступная аудитория.
  • При нулевом бюджете SMS-пилоты невозможны и агент строит план без пилотов; по ТЗ бюджет всегда 100 000 у.е., поэтому на проверке этот случай не возникает.
  • В независимых трудных сценариях встречались убыточные прогоны. Положительный результат всех опубликованных сценариев не является универсальной гарантией.
  • plan_table содержит модельные оценки; скорер дополнительно учитывает обрезку охвата и дедупликацию. Панель показывает эти величины отдельно.
  • Числа зависят от кода, данных и библиотек. Опубликованный стресс-отчёт не пересчитывается при открытии панели; локальные прогоны запускаются кнопками.
  • Агент оптимизирует чистый прирост ARPU оператора. Выгода для абонента (соответствие пакета потреблению, удовлетворённость, риск оттока) в модели не учитывается; downsell отсекается только как потеря выручки.
  • Ассистент панели в локальном режиме не анализирует вопрос, а показывает общее объяснение плана; ответ на произвольный вопрос возможен только в режиме LLM с ключом.
  • Промышленное развёртывание и API-интеграции с оператором не реализованы.

Применение

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

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

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

Развитие

Следующие направления пока не реализованы:

  • Выбор канала внутри data/call-сегментов с учётом различий ARPU и экспериментальной проверки.
  • Размер пилота по ценности информации, а не преимущественно максимальный размер.
  • Групповые пилоты по нескольким ячейкам с корректной моделью наблюдения.
  • Разведка переходов, отсутствующих в исторической выборке.
  • Расширение ассистента аналитика: проверка качества ответов, история диалога и ссылки на конкретные пилоты.
  • Ежемесячная калибровка по фактическому отклику и мониторинг сдвига аудитории.
  • Учёт выгоды абонента: ограничение на переходы, при которых пакет хуже соответствует потреблению, и совместная цель «выручка оператора + удержание абонента».
  • Локальные ответы на типовые вопросы аналитика («почему отклонена гипотеза», «зачем этот канал») по журналу решений без внешнего API.

Сторонние компоненты и AI-инструменты

Среда, скорер, шаблон, генератор submission и синтетические данные предоставлены организаторами кейса Beeline. Используются pandas, NumPy, SciPy (решатель HiGHS) и Streamlit. Стенд tools/realistic_bench.py подготовлен независимым ревьюером. Разработка, ревью, документация и тестирование выполнялись с помощью Claude (Anthropic) и ChatGPT/Codex (OpenAI). Во время исполнения агент не вызывает эти системы; объяснение строится локально из журнала решений. Ботанические изображения assets/botanical.png и assets/vines.png созданы с помощью OpenAI ImageGen для оформления панели; персонажи не используются. Внешний OpenAI API применяется только в явно включённом ассистенте панели. Пакет openai не требуется: существующая интеграция использует стандартную библиотеку Python и Responses API.

Соответствие требованиям к README

Пункт 5.4.15 положения HackAlem AI и Приложение 2, п. 7:

ТребованиеРаздел
Описание решения и его назначенияПроблема и пользователь, Что реализовано
Описание архитектурыТехнологии и архитектура, Структура репозитория
Используемые технологииТехнологии и архитектура, Метод
Инструкции по установке и необходимые зависимостиУстановка
Инструкции по запускуБыстрая проверка, Запуск
Параметры окруженияУстановка: обязательных переменных нет
Порядок проверки основного сценарияПроверка за 5 минут
Данные и внешние сервисыДанные и интеграции
Известные ограниченияОграничения
Ссылка на развёрнутую версиюДеплой: публичного размещения нет, запуск локально
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
17
Авторы
1
Файлы
34
Ветки
1

Авторы коммитов

ahmetkali23-hue 17

История коммитов

  • 2026-09-23 17:24Документация по аудиту Codex: протокол проверок, точные формулировки; числа прописью в проверке ассистентаahmetkali23-hue
  • 2026-09-23 17:16Ассистент: точность чисел по записи, округлённый контекст, узкий фильтр выгоды абонента, честная формулировка про downsellahmetkali23-hue
  • 2026-09-23 17:11Панель: убраны залипающие всплывающие подсказки у кнопок «Спросить AI» и «Свернуть»ahmetkali23-hue
  • 2026-09-23 17:08Ассистент панели: чат «Спросить AI», ключ из .env, ответы только по теме кейса, защита от выдуманных чисел и фактовahmetkali23-hue
  • 2026-09-23 16:49Панель: читаемость — разделители разрядов, понятные названия кампаний, контраст подписейahmetkali23-hue
  • 2026-09-23 16:41README: результат коротко, оглавление, mermaid-архитектура, структура репозитория, соответствие п. 5.4.15ahmetkali23-hue
  • 2026-09-23 16:36Панель: отрицательные результаты видны явно, стенды раздельно; README: быстрая проверка и тестыahmetkali23-hue
  • 2026-09-23 16:29Агент: правило риска и в запасном планировщике, честное объяснение доп. push; регрессионные тестыahmetkali23-hue
Все коммиты (17)
  • 2026-09-23 16:15README под v5 и демо-панель: Streamlit-панель, зависимости панели, исправленный .env.exampleahmetkali23-hue
  • 2026-09-23 15:44docs: итог v5 на полном стенде 15x5, версии и размеры проверок, журнал отклонённых экспериментов, источники цитатahmetkali23-hue
  • 2026-09-23 15:12Агент v5: правило риска по состоянию модели — без рискованного push, если история ненадёжнаahmetkali23-hue
  • 2026-09-23 15:01tools: сравнение версий агента, калибровка стенда по подсказке ТЗ, стенд реалистичных сценариевahmetkali23-hue
  • 2026-09-23 14:41Агент v4: MILP-планировщик целых ячеек, страховка от ошибок солвера; исправлено расхождение плана с фактомahmetkali23-hue
  • 2026-09-23 14:29Агент v3: неопределённость по конверсии, эмпирический Байес, push на остаток; честный оракул в стендеahmetkali23-hue
  • 2026-09-23 13:53Агент v2: Knowledge Gradient, калибровка истории по пилотам, эмпирический Байес, выбор каналаahmetkali23-hue
  • 2026-09-23 13:41docs: план работ, архитектура агента, распределение задач между AI-агентамиahmetkali23-hue
  • 2026-09-23 13:23Каркас проекта: пакет кейса Beeline, бейзлайн-агент, READMEahmetkali23-hue
Структура репозитория (34 файлов)
.env.example
.gitignore
README.md
agent.py
agent_template.py
app.py
assets/botanical.png
assets/vines.png
customer_profile.csv
data/arpu_monthly.csv
data/change_tariff.csv
data/dict_tariff.csv
data/traffic.csv
docs/CHATGPT_PROMPT.md
docs/PARTICIPANT_GUIDE.md
docs/PLAN.md
docs/RESULTS.md
docs/VERIFICATION.md
environment.py
feature_dictionary.csv
local_eval.py
make_submission.py
mock_environment.py
requirements-app.txt
requirements.txt
scoring_core.py
stress_eval.py
submission.csv
tariff_dictionary.csv
tests/test_agent_regressions.py
tools/compare_versions.py
tools/no_exploration_check.py
tools/realistic_bench.py
ui_i18n.py

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.