О проекте
Команда: HaveFun
Кейс HackAlem.ai: Телеком — Beeline
Стадия: Рабочий MVP
Задача кейса: Агент, который решает, каким абонентам какой тариф предложить (чистый прирост ARPU)
Суть
Агент для аналитика Beeline, который выбирает сегменты абонентов, целевые тарифы и каналы, проверяет гипотезы пилотами и выдаёт план кампаний, максимизирующий прирост ARPU за вычетом стоимости контактов.
Как устроено
По data/change_tariff.csv строится исторический приор по паре сегмент × целевой тариф. Гипотезы ранжируются, часть из 20 пилотов резервируется под сегменты с отрицательным приором; push-пилоты по 100–200 контактов дают шумные наблюдения. Затем гипотезы отбираются по оценке эффекта с поправкой на шум, делается ограниченный перенос на непилотированные группы, аудитория разбивается под лимиты (≤10 кампаний, ≤5000 контактов на кампанию, 100 000 у.е.) и каналы распределяются по ожидаемой экономике. LLM только формулирует объяснение.
Ключевые решения
- Bayesian-style historical prior
- pilot experiments (explore/exploit)
- noise-adjusted effect estimation
- budget/channel allocation
- scenario stress testing (7 worlds)
- multi-seed stability check
Метрики
seed 42: чистый результат 4 485 142 у.е., затраты 91 252/100 000; 5 из 5 seed в плюс, медиана 4 267 953; 7 миров эффектов пройдены
Особенности
Проверка устойчивости стратегии на 7 альтернативных «мирах» эффектов (включая нулевую и убыточную модели) и по нескольким seed; честный учёт пилотных контактов в бюджете и двойного счёта при пересечениях аудиторий. Код перенесён в репозиторий импортом архивов.
Стек
Python · pandas · numpy · FastAPI · uvicorn · Docker Compose · DaisyUI · Tailwind · Chart.js
Модели
OpenAI
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ea42dc67-havefun.
README
README.mdАгент управления тарифными маркетинговыми кампаниями
Трек 04 «Телекоммуникации», кейс Beeline, HackAlem AI.
Агент помогает аналитику выбрать сегменты абонентов, целевые тарифы и каналы связи. Он проверяет гипотезы пилотами и возвращает план маркетинговых кампаний. Цель — прирост ARPU за вычетом стоимости коммуникаций, включая пилоты.
Все данные и эффекты синтетические. Это учебная симуляция из пакета организатора, а не реальные показатели Beeline и не доказанная прибыль на реальных клиентах.
Проверенные результаты
Числа ниже относятся к коду версии 48fe4e4, стандартным настройкам и указанным seed. Скрытая модель судейства отличается от локальной; эти результаты не предсказывают место.
| Проверка | Результат |
|---|---|
| Основной прогон, seed 42 | PASS; чистый результат 4 485 142,41 у.е. |
| Затраты на коммуникации | 91 252 из 100 000 у.е. |
| Все контакты / уникальные абоненты | 9 069 / 7 213 |
| Пилоты | 20, фактически 3 356 контактов |
| Финальный план | 2 кампании, 5 713 контактов |
| Пять прогонов, seed 0–4 | 5 из 5 в плюс |
| Медиана / минимум / максимум этих пяти прогонов | 4 267 953 / 3 801 597 / 4 809 185 |
| Самопроверка | Завершилась успешно: «ВСЁ ПРОШЛО» |
| submission.csv | Сохранённый файл совпал с генерацией в проверке |
| CLI и HTTP, seed 42 | Дали одинаковый численный результат |
Финальный план на seed 42:
| Кампания | Канал | Контакты | Расходы |
|---|---|---|---|
| MID → tariff_8 | digital_ads | 3 800 | 83 600 |
| LOW → tariff_9 | sms | 1 913 | 7 652 |
Пилотные контакты и финальные контакты суммируются: 3 356 + 5 713 = 9 069. Уникальных клиентов меньше из-за пересечений. Прирост оценивается по лучшей кампании для каждого клиента; простое сложение отдельных эффектов может дать двойной учёт.
Проверки выполнены в Linux-контейнере с Python 3.12, без сети и без API-ключа. Использовался ранее подготовленный образ зависимостей с кодом 48fe4e4, подключённым только для чтения. Это проверка текущего кода, а не заявление о новой чистой сборке образа. Live API языковой модели в этой проверке не использовался.
Установка и основной сценарий
Нужен Python 3.11+; приведённые результаты получены на Python 3.12. Выполняйте команды из корня репозитория: пути к данным относительные.
python -m venv .venv
Активация в PowerShell:
.\.venv\Scripts\Activate.ps1
Активация в macOS/Linux:
source .venv/bin/activate
Установка зависимостей и проверка:
python -m pip install -r requirements.txt
python local_eval.py
python local_eval.py --runs 5
python selfcheck.py
python scenarios.py
python make_submission.py
Основной прогон должен завершиться со статусом PASS и сформировать корректные кампании. Точный состав плана зависит от наблюдений пилотов; не фиксируйте его для всех seed. make_submission.py создаёт submission.csv в формате организатора. requirements.txt содержит pandas, numpy, FastAPI, uvicorn и SDK openai. Версии заданы нижними границами, поэтому будущая установка может разрешить другие версии.
Веб-интерфейс
python app.py
Откройте http://localhost:8000; проверка сервиса — http://localhost:8000/api/health. Интерфейс показывает разведку, финальные кампании, общий результат и журнал гипотез. Доступны сравнение стратегий, устойчивость, сценарии других эффектов и изменение бюджета. Кнопка экспорта плана создаёт CSV для аналитика; это отдельный формат, не submission.csv.
Проверенный пересчёт бюджета на seed 42:
| Бюджет | Чистый результат | Расходы | Уникальные клиенты | Каналы |
|---|---|---|---|---|
| 25 000 | 3 809 773,28 | 22 852 | 7 213 | две SMS-кампании |
| 50 000 | 3 809 773,28 | 22 852 | 7 213 | две SMS-кампании |
| 100 000 | 4 485 142,41 | 91 252 | 7 213 | реклама и SMS |
Одинаковый охват в этих трёх случаях не означает исчерпания лимита контактов. Оформление и графики используют DaisyUI, Tailwind и Chart.js через внешние CDN. Основной расчёт без ключа работает офлайн; полностью автономное браузерное демо не заявляется.
Docker
В репозитории есть Dockerfile, docker-entrypoint.sh и docker-compose.yml. Первая сборка требует доступ к реестру образов и Python-пакетам.
docker build -t hackalem-agent .
docker run --rm hackalem-agent
docker run --rm hackalem-agent selfcheck
docker run --rm hackalem-agent stability
docker run --rm hackalem-agent scenarios
docker run --rm hackalem-agent submission
docker run --rm -p 127.0.0.1:8000:8000 hackalem-agent web
Вариант через Compose:
docker compose up --build
docker compose run --rm agent selfcheck
docker compose run --rm agent scenarios
docker compose down
Compose публикует порт 8000 согласно docker-compose.yml; интерфейс — http://localhost:8000. Образ содержит HEALTHCHECK для HTTP-сервиса. CLI-команды завершаются после выполнения. Режим submission записывает CSV внутри контейнера; с --rm файл исчезает вместе с ним. Для файла на компьютере используйте python make_submission.py либо скопируйте его из сохранённого контейнера командой docker cp. Базовый тег python:3.12-slim изменяемый; побитовая повторяемость будущих сборок не гарантируется.
Как принимает решение агент
- Строит исторический приор по сегменту и целевому тарифу из data/change_tariff.csv.
- Ранжирует гипотезы и резервирует часть пилотов для сегментов с отрицательным приором.
- Проводит push-пилоты: они бесплатны по стоимости связи, но расходуют контакты и могут уменьшить ARPU. Основной размер — 200, разведочный — 100; малые группы меньше.
- Отбирает гипотезы по оценке эффекта с поправкой на шум.
- Сохраняет измеренные пары «исходный тариф → цель» при объединении кампаний; для непилотированных групп использует ограниченный перенос внутри сегмента.
- Разбивает аудиторию под лимиты и распределяет каналы по ожидаемой экономике.
- Возвращает план; языковая модель при наличии доступа только формулирует объяснение.
Лимиты кейса: до 10 финальных кампаний, до 5 000 контактов на кампанию, до 15 000 контактов и 100 000 у.е. суммарно с пилотами; до 20 пилотов. Параметры шума, размеров пилотов и порога уверенности заданы в agent.py. Они не все выводятся из данных. История задаёт предположения, пилоты дают шумные наблюдения.
Другие модели эффектов
CLI-команда python scenarios.py проверяет 7 миров, каждый на seed 0 и 1. Веб-кнопка и /api/scenarios сейчас показывают 6 базовых миров; регрессионный мир с разными целями у источников проверяется дополнительно через CLI.
| Мир | Средний чистый результат |
|---|---|
| Как в истории | 3 168 084 |
| Прибылен HIGH | 4 874 524 |
| Прибылен только MID | 2 489 736 |
| Всё слабо растёт | 154 509 |
| Всё убыточно | −738 699 |
| Нулевая модель | −1 812 |
| Разные цели у исходных тарифов | 3 133 322 |
Все семь прошли критерии скрипта. Для миров «около нуля» разрешён убыток до 0,5% baseline, примерно 753 205 у.е. Поэтому «пройдено» не означает отсутствие потерь. В нулевой модели seed 0 дал 0, seed 1 — −3 624: даже там возможны расходы на кампании. Два seed и ограниченный набор миров не доказывают устойчивость на любых скрытых эффектах.
Ограничения и границы проверки
- Агент может вернуть пустой план, если не нашёл приемлемых гипотез. Это не гарантирует отсутствие прибыльных возможностей. Требование кейса «1–10 кампаний» формально не выполнено при нуле; допустимость такого отказа должен подтвердить организатор.
- Пустой финальный план не отменяет эффекты уже проведённых пилотов.
- Перенос на непилотированные группы остаётся предположением и может ошибаться.
- Оценка выгоды каналов приближённая: насыщение конверсии не определяется полностью одним push-пилотом. Запас для дорогих каналов не гарантирует оптимальный выбор.
- selfcheck.py проверяет перечисленные в нём случаи, включая искусственный отказ функции объяснения. Он не заменяет проверку всех данных, лимитов и конкурентных запросов.
- Проверенные отрицательные seed в run, ask и CSV возвращают HTTP 422. Последовательная проверка настроек не обнаружила прежнего влияния на stability; это не исчерпывающая гарантия для всех параллельных запросов.
Языковая модель и окружение
OPENAI_API_KEY необязателен. Без него объяснение собирается локально по шаблону, а вопросы к модели возвращают сообщение о недоступности. Числовой план не зависит от LLM. При наличии ключа выполняются внешние API-вызовы; возможны расходы по условиям провайдера. OPENAI_MODEL задаёт желаемую модель; без него explain.py пытается выбрать доступную. Compose передаёт OPENAI_API_KEY, но OPENAI_MODEL при необходимости нужно добавить отдельно. Для Docker можно передать переменные через -e OPENAI_API_KEY -e OPENAI_MODEL, предварительно установив их в окружении. Не сохраняйте ключи в исходниках. TRANSFER_TO_SEGMENT=0 отключает перенос на непилотированные группы; стандартный режим — 1.
Данные и файлы
Данные организатора: customer_profile.csv, data/change_tariff.csv, data/dict_tariff.csv и словари признаков/тарифов. Аудитория — 23 441 строка, история — 14 823 строки. agent.py содержит стратегию; app.py и web/index.html — HTTP-сервис и интерфейс. explain.py отвечает за объяснения; selfcheck.py, scenarios.py и sweep.py — проверки. local_eval.py, make_submission.py и scoring_core.py происходят из пакета организатора. Описание кейса сохранено в docs/PARTICIPANT_GUIDE.md.
Авторы коммитов
История коммитов
- 2026-09-24 05:58fix: honor explicit model override and refresh verified READMEDamira Baltasheva
- 2026-09-24 05:44feat: import fifth archive with agent and interface updatesDamira Baltasheva
- 2026-09-24 04:53chore: import fourth archive with review prompt and self-check updatesDamira Baltasheva
- 2026-09-24 04:49feat: import third archive with Docker setup and learning logDamira Baltasheva
- 2026-09-24 04:22feat: update campaign agent and analyst interface from second archiveDamira Baltasheva
- 2026-09-24 03:54feat: import Beeline tariff campaign projectDamira Baltasheva
- 2026-09-24 03:11docs: add track analysis and three-hour Codex planDamira Baltasheva
- 2026-09-24 02:26chore: remove test filesDamira Baltasheva
Все коммиты (10)
- 2026-09-23 14:08chore: add test commitDamira Baltasheva
- 2026-09-23 14:01Create TestingDamira Baltasheva
Структура репозитория (32 файлов)
.claude/launch.json .dockerignore .gitattributes .gitignore Dockerfile README.md TRACK-ANALYSIS-3H.md TRACK-ANALYSIS.md agent.py agent_template.py app.py customer_profile.csv data/change_tariff.csv data/dict_tariff.csv docker-compose.yml docker-entrypoint.sh docs/PARTICIPANT_GUIDE.md docs/REVIEW-PROMPT.md environment.py explain.py feature_dictionary.csv local_eval.py make_submission.py mock_environment.py requirements.txt scenarios.py scoring_core.py selfcheck.py submission.csv sweep.py tariff_dictionary.csv web/index.html
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.