tariff campaign agent
Офлайн-агент Agent.act(env) для Beeline проверяет тарифные переходы пилотными кампаниями и возвращает 1–10 финальных кампаний с максимальным…
О проекте
Команда: Dara Vision
Кейс HackAlem.ai: Телеком — Beeline
Стадия: Доведённый продукт
Задача кейса: Агент, который решает, каким абонентам какой тариф предложить (чистый прирост ARPU)
Суть
Офлайн-агент Agent.act(env) для Beeline проверяет тарифные переходы пилотными кампаниями и возвращает 1–10 финальных кампаний с максимальным оценённым приростом ARPU. LLM опционально пишет только объяснение запуска.
Как устроено
Абоненты делятся на сегменты «текущий тариф × ARPU», крупные группы дополнительно делятся по data/call-сегменту. История переходов ранжирует гипотезы; первые 16 пилотов идут по истории, последние 4 выбираются по приближённой ценности информации с учётом затрат. Оценки эффекта стягиваются к нулю (вес 80 наблюдений), малые выборки штрафуются за неопределённость. Затем точным перебором портфеля среди ≤20 измеренных комбинаций выбирается максимум добавочного эффекта с учётом пересечения с пилотами, при ограничениях бюджета, контактов, 10 кампаний и одного варианта на сегмент.
Ключевые решения
- segmentation tariff×ARPU
- value-of-information pilot selection
- shrinkage estimator
- uncertainty penalty
- exact portfolio search under constraints
- expected overlap modeling
- paired seed benchmark
- OpenAI Responses closed-vocabulary explanation
Метрики
mock seed 0–9: 10/10 положительных, медиана 3 399 849, мин 2 507 992, макс 3 564 974; воспроизводимый submission.csv (seed 42, SHA-256)
Особенности
Задача решена как активное исследование с бюджетом: сначала пилоты, выбранные по ценности информации, затем точная оптимизация портфеля с учётом пересечения выборок. Бенчмарк парный против базовой версии на нескольких синтетических сценариях (нулевой эффект, убыточный, редкие прибыльные переходы). LLM-объяснение ограничено закрытым словарём фраз, чтобы модель не придумывала чисел.
Стек
Python 3.12 · pytest
Модели
OpenAI Responses API (OPENAI_EXPLANATION_MODEL, опционально только для объяснений)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-534039b4-dara-vision.
README
README.mdHackAlem Track 04: tariff campaign agent
Офлайн-агент Agent.act(env) исследует тарифные переходы пилотами и возвращает
1–10 кампаний. История используется как подсказка; финальный план состоит только
из проверенных пилотами комбинаций. Агент не читает модель эффектов, не использует
сеть, LLM или секреты среды.
Запуск
Python 3.12+; зависимости закреплены в requirements.txt. Из корня репозитория:
python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python -m pytest -q
python local_eval.py
python local_eval.py --runs 10
python make_submission.py
sha256sum submission.csv
make_submission.py использует seed 42. Повторный запуск создаёт тот же CSV.
Указанное официальным evaluator число кампаний включает пилоты; лимит 10
применяется к возвращённому финальному списку.
Проверено перед финальной сдачей на штатном mock:
seed 0–9: 10 из 10 результатов положительны
медиана: 3,399,849
минимум: 2,507,992
максимум: 3,564,974
seed 42 submission.csv SHA-256:
4198927766416446991f4090f4071759a3c5dac3bceac9c0066eaed6a8272022
Это воспроизводимый локальный результат на синтетическом evaluator, а не гарантия скрытого judge или реального бизнес-эффекта.
Как принимаются решения
- Публичный профиль разбивается на непересекающиеся текущий тариф × ARPU сегменты. Группы больше 5000 дополнительно делятся по data/call segment.
- История ранжирует переходы и каналы. Первые 16 наблюдений сохраняют историческую разведку baseline, включая повторное измерение текущего лидера. Исторический shortlist задаёт начало порядка, но остальные допустимые комбинации сохраняются.
- Последние четыре пилота выбираются по приближённой ценности информации: ожидаемому улучшению относительно лучшего измеренного варианта для того же сегмента, с учётом затрат и ожидаемого отрицательного эффекта самого пилота. Можно уточнить пограничную кампанию, исследовать новый переход или остановиться. Новая гипотеза получает 100 контактов, повторная — до 200; call — до 50.
- Средний эффект взвешивается по числу контактов и стягивается к нулю с весом 80 условных наблюдений. Малые выборки получают дополнительный штраф за неопределённость; при отрицательном среднем результате разведки штраф сохраняется и для больших выборок. Это эвристика риска, а не доверительный интервал или гарантия статистической значимости.
- Планировщик оценивает добавочный эффект финальной кампании после пилотов. При частичном охвате он использует ожидаемое пересечение независимых случайных выборок; повторный полный охват уже проверенного сегмента не даёт новый lift.
- Точный поиск портфеля среди не более 20 измеренных комбинаций выбирает максимум суммарного оценённого эффекта с ограничениями бюджета, контактов, десяти кампаний и одного варианта на сегмент. Порядок выдачи детерминирован.
Перед каждым пилотом проверяются публичные остатки ресурсов; резерв сохраняет возможность хотя бы одной финальной кампании. На пилоты уходит не более 25% начального денежного бюджета. Ошибка пилота останавливает разведку без повтора вызова. Если прибыльных оценок нет, агент по возможности измеряет небольшой бесплатный сегмент и возвращает наименее убыточный измеренный вариант, поскольку контракт требует хотя бы одну кампанию. Бесплатный канал всё равно может снижать ARPU и расходует контакты.
Agent.trace содержит запросы и результаты пилотов, остатки ресурсов и финальные
решения. final_selected.estimated_score — оценка добавочного эффекта после
дедупликации с пилотами. Точное пересечение ID и истинный результат считает только
официальный scorer.
Воспроизводимое сравнение с b70e366
python scripts/compare_candidate.py --seeds 10 --out reports/candidate-standard.json
python scripts/compare_candidate.py --start 100 --seeds 10 --model-seed 20261001 --out reports/candidate-holdout.json
python scripts/compare_candidate.py --start 200 --seeds 10 --model-seed 20261002 --scenarios weak sparse dense saturated --out reports/candidate-holdout2.json
python scripts/compare_candidate.py --start 300 --seeds 10 --model-seed 20261003 --scenarios weak sparse dense saturated --out reports/candidate-final-validation.json
python scripts/compare_candidate.py --start 42 --seeds 1 --scenarios mock --out reports/candidate-seed42.json
Нужна Git-история с b70e366: runner загружает четыре исходных модуля baseline
в отдельные пространства имён, не переключает ветки и не изменяет файлы.
Для обоих агентов используются одинаковые данные, модель и seed шума. Собственные
модели живут только в evaluator и передаются публичной make_environment; агент
получает исключительно env. В JSON сохраняются все результаты, нарушения,
время и SHA-256 проверенных исходников.
Сценарии: официальный mock, нулевой эффект, все переходы убыточны, слабые эффекты,
редкие прибыльные переходы, смешанные эффекты и насыщение конверсии. Это конечный
набор синтетических проверок, а не оценка будущего балла. Подробные числа,
регрессии и рекомендация интеграции — в отчёте кандидата.
Предыдущие reports/development*, reserved* и integration.md относятся к старой
версии и не подтверждают качество текущего кандидата. scripts/evaluate.py
по-прежнему доступен для сравнения с официальным template, а не с b70e366.
Упаковка и ограничения
Для сдачи нужны agent.py, contracts.py, planning.py, policy.py, submission.csv
и зависимости из requirements.txt; одним agent.py многомодульное решение не
ограничивается. Положите рядом data/change_tariff.csv, чтобы воспроизвести
историческое ранжирование. При отсутствии истории агент работает с публичными
профилем и тарифами, но его решения и score могут отличаться. Полный репозиторий
содержит также официальную среду, данные и команды воспроизведения.
Первые 16 пилотов ещё зависят от истории. Четыре поздних пилота не гарантируют обнаружения редкой прибыльной комбинации. Гауссовская оценка использует опубликованный масштаб шума 0.804; она не калибрована для другого шума или адаптивного отбора. Модель ожидаемого пересечения предполагает равномерные независимые пилотные выборки. Точный подбор максимизирует оценку, а не неизвестный истинный эффект.
Все исходные файлы организаторов и данные сохранены по SHA-256 из
provenance.json; атрибуция — в THIRD_PARTY.md.
Никаких гарантий положительного результата на скрытом judge или реальной базе нет.
Объяснение одного запуска
python scripts/explain_run.py --out reports/explanation
Команда вызывает Agent.act ровно один раз через официальный evaluate_agent.
Сохраняет plan.json, trace.json, local_evaluator.json, facts.json,
explanation.json и русский explanation.md. Числа берутся только из Python;
неизвестные и нечисловые значения представлены null / «неизвестно» (включая
бесконечный ROI в сохранённом evaluator). Идентификатор c01 означает первую
кампанию plan.json, eN — событие trace с step=N. История, шумные наблюдения
пилотов, эвристические оценки агента и локальный результат разделены.
По умолчанию используется детерминированный офлайн-шаблон. Обычные
local_eval.py и make_submission.py всегда остаются офлайн, даже при наличии
API-переменных. Объяснение не меняет план, пилоты, ресурсы или CSV.
Опциональный режим требует официального Python SDK, который не нужен агенту:
pip install openai
cp .env.example .env
# Заполните .env локально: новый ключ и доступная вам модель Responses API.
set -a
. ./.env
set +a
python scripts/explain_run.py --llm --out reports/explanation
Не используйте ключи из переписки; создайте новый ключ локально. Секреты не
печатайте и не добавляйте в Git. .env и .env.* игнорируются, .env.example
содержит только пустые переменные. Файл .env автоматически не загружается:
конфигурация читается исключительно из окружения и только при --llm.
OPENAI_API_KEY и OPENAI_EXPLANATION_MODEL обязательны для LLM.
OPENAI_EXPLANATION_TIMEOUT_SECONDS по умолчанию 20 (допустимо >0 и <=120),
OPENAI_EXPLANATION_MAX_OUTPUT_TOKENS по умолчанию 2000 (1–8000).
Выполняется максимум один запрос Responses, max_retries=0, store=False,
без tools и web search. Используется
официальный формат Responses text.format.
Payload ограничен 48000 байт и содержит только разрешённые агрегированные факты,
без CSV, строк абонентов и ID_NUMBER. Ссылки проверяются не только на существование,
но и на принадлежность кампании. Свободный текст LLM намеренно запрещён:
структурированный русский JSON использует закрытый словарь проверенных фраз,
чтобы модель не добавляла числа, кампании и неподтверждённые утверждения.
Нет ключа/модели/SDK, неверные настройки, timeout, 401/429/5xx, неполный ответ, невалидный JSON или ссылки — сохраняется офлайн-шаблон с безопасным кодом fallback. Тексты исключений и сырые ответы модели не сохраняются. Общий deadline работает через POSIX timer в главном потоке; на неподдерживаемой платформе, в другом потоке или при уже активном timer выполняется fallback до запроса. Все данные синтетические; локальный результат не гарантирует скрытый балл или реальный бизнес-эффект.
Авторы коммитов
История коммитов
- 2026-09-23 17:52docs: add offline run explanationsmilord-x
- 2026-09-23 17:34feat: broaden adaptive tariff explorationAnyoz1
- 2026-09-23 16:51wip: add red team optimization checkpointmilord-x
- 2026-09-23 16:51wip: optimize adaptive allocation checkpointAishaZhenisbekqz
- 2026-09-23 16:51wip: optimize exploration policy checkpointAnyoz1
- 2026-09-23 15:52merge: integrate Astra hardening reviewmilord-x
- 2026-09-23 15:52fix: make evaluation runner portable and signal failuresAishaZhenisbekqz
- 2026-09-23 15:52test: cover input validation and fallback contractsAnyoz1
Все коммиты (26)
- 2026-09-23 15:01Add contributor verification ownershipAishaZhenisbekqz
- 2026-09-23 15:01Document contributor roles and reproducibility ownershipAnyoz1
- 2026-09-23 15:01Merge agent-2 history into final integrated solutionmilord-x
- 2026-09-23 14:56Record integrated benchmark reproduction and verified demomilord-x
- 2026-09-23 14:55Integrate strongest campaign policy with numeric ARPU fix and audited reportingmilord-x
- 2026-09-23 14:53Merge pull request #1 from BAITC-Hacks/hackalem/agent-2AishaZhenisbekqz
- 2026-09-23 14:52Finalize demo guidance and numeric ARPU handlingmilord-x
- 2026-09-23 14:51Document release demo and reproducibilitymilord-x
- 2026-09-23 14:51Document final submission verification hashmilord-x
- 2026-09-23 14:49Validate pilot sample counts and verify offline submissionmilord-x
- 2026-09-23 14:46Record paired development and reserved evaluationsmilord-x
- 2026-09-23 14:46Record frozen-policy paired benchmark and final submissionmilord-x
- 2026-09-23 14:45Build offline pilot-driven tariff campaign agentmilord-x
- 2026-09-23 14:45Add reproducible benchmark, acceptance tests and setup guidemilord-x
- 2026-09-23 14:45Record fixed-policy holdout results and pinned installmilord-x
- 2026-09-23 14:43Build offline tariff campaign agent and evaluation pipelinemilord-x
- 2026-09-23 14:40Implement offline feedback-driven campaign agentmilord-x
- 2026-09-23 14:38Import verified official participant package and provenancemilord-x
Структура репозитория (48 файлов)
.env.example .gitignore CONTRIBUTORS.md PARTICIPANT_GUIDE.md PARTICIPANT_GUIDE.pdf README.md THIRD_PARTY.md agent.py agent_template.py contracts.py customer_profile.csv data/arpu_monthly.csv data/change_tariff.csv data/dict_tariff.csv data/traffic.csv environment.py explanations.py feature_dictionary.csv local_eval.py make_submission.py mock_environment.py planning.py policy.py provenance.json reporting.py reports/comparison/agent-1-reserved.json reports/comparison/agent-2-reserved.json reports/comparison/agent-3-reserved.json reports/development-trace.json reports/development.json reports/development.md reports/integration.md reports/reserved-trace.json reports/reserved.json reports/reserved.md requirements.txt scoring_core.py scripts/compare_candidate.py scripts/evaluate.py scripts/explain_run.py submission.csv tariff_dictionary.csv tests/test_acceptance.py tests/test_agent.py tests/test_explanations.py tests/test_planning.py tests/test_policy.py tests/test_reporting.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.