AAYMA
RU
Войти

Adaptive Campaign Portfolio Agent

Агент тарифных кампаний Beeline. Ранжирует гипотезы по истории смен тарифов, проверяет их адаптивными SMS-пилотами и оптимизатором собирает портфель…

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

О проекте

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

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

Суть

Агент тарифных кампаний Beeline. Ранжирует гипотезы по истории смен тарифов, проверяет их адаптивными SMS-пилотами и оптимизатором собирает портфель до 10 кампаний под бюджет и лимит контактов.

Как устроено

candidate_engine ранжирует до 40 гипотез по истории со shrinkage и учётом разнообразия ячеек. pilot_policy запускает до 10 разведочных пилотов по 80 контактов и до 5 подтверждений по 200. portfolio_optimizer одновременно выбирает канал (push/SMS/digital_ads), тариф и пропуск ячейки по mean/SE/safe lift; call исключён из-за насыщения конверсии. LLM-советник (OpenAI) видит только агрегаты гипотез и может предложить до двух пилотов. По умолчанию его ответ воспроизводится офлайн из artifacts/llm_policy.json по хешу контекста.

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

  • historical shrinkage ranking
  • adaptive pilots
  • portfolio optimization under budget/reach
  • safe lift (mean − SE)
  • LLM replay by context hash

Метрики

Mock evaluator, seeds 0–9: средний net gain 2,898,763.77 против −480,836 у starter; положительных прогонов 10/10; seed 42 — 3,206,241.49; 147 тестов прошли

Особенности

Команда честно пишет, что LLM рост прибыли не дал: 11 живых запросов выбрали те же гипотезы, что и численный план. Детерминированный replay LLM-ответа по хешу контекста делает submission воспроизводимым. Опция adaptive_confirmation_n выключена по умолчанию, потому что ухудшила минимум.

Стек

Python · pandas · NumPy · pytest

Модели

OpenAI


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

README

README.md

Adaptive Campaign Portfolio Agent

Решение синтетического кейса Beeline для AI-хакатона. История переходов ранжирует гипотезы, SMS-пилоты измеряют эффект на текущей аудитории, а оптимизатор выбирает до 10 кампаний с учётом неопределённости, бюджета и охвата. Итоговая версия объединена в main. Все команды выполняются из корня репозитория.

Обычный Agent() работает без сети и ключа: применяет сохранённую LLM-рекомендацию при точном совпадении входного контекста, иначе использует численную политику. Явный live-режим OpenAI доступен отдельно. Веса модели не обучались.

Быстрый запуск на новой машине

Нужны Git и Python 3.12. Проверенное окружение: Python 3.12.3, pandas 3.0.3, NumPy 2.4.4, pytest 9.0.2. Зависимости закреплены в requirements-файлах.

git clone --branch main https://github.com/BAITC-Hacks/hack-dd3ffc75-aid-soccer.git
cd hack-dd3ffc75-aid-soccer

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt -r requirements-llm.txt

python -m pytest tests -q
python local_eval.py
python local_eval.py --runs 10
python -m tools.benchmark --runs 10 --compare-starter --trace-seed 42
python make_submission.py
python -m reporting --input reports/decision_trace.json --output reports/demo.html

Для работы обычного агента достаточно requirements.txt. Для полного набора тестов, включая SDK через mock HTTP transport, команда выше также устанавливает зависимости разработки и LLM. Тесты не вызывают внешний API. API-ключ для официального evaluator и генерации submission не требуется.

Публичные CSV и неизменённые скрипты организаторов включены в репозиторий. Папка beeline_case_participants с пробелом в конце содержит предыдущий прототип; запускайте корневые скрипты, не эту копию. task/ для запуска не нужен.

Проверенные результаты

147 тестов прошли, в том числе в чистом экспорте без .env и task/. В отдельной проверке чистого экспорта submission воспроизвёлся при отключённых сети и импорте необязательных OpenAI SDK / dotenv.

Публичный mock evaluator, одинаковые seed 0–9 для нашего агента и starter:

Метрика net gain, у.е.Итоговый агентИсходный agent_template
Среднее2,898,763.77-480,836.18
Медиана3,103,097.10-357,947.80
Минимум1,567,730.55-1,019,431.06
Положительных прогонов10/100/10

Побед по одинаковым seed: 10/10. Starter оценивался без изменений: на seed 3 он вернул ноль финальных кампаний; его фактический результат только от пилотов включён в сравнение и отмечен meets_final_count_requirement=false.

Во всех десяти прогонах итогового агента: 15 пилотов, 3–6 финальных кампаний, нет отброшенных кампаний и усечения по остаткам бюджета/охвата. Максимальные расходы — 96,542 / 100 000, контакты — 8,201 / 15 000. Максимальное измеренное время полного прогона — 0.599 с на проверенной машине; это офлайн-замер, не оценка задержки live API. Лимит задания — 600 секунд.

Seed 42: net gain 3,206,241.49, 15 пилотов + 4 финальные кампании, расходы 74 256, контакты 4 848. Число 19 в официальном отчёте включает пилоты; лимит 10 относится к финальному списку. После всего плана остаётся 25 744 бюджета; остаток, напечатанный evaluator после пилотов, отличается.

Доказательства: официальные 10 seed, seed 42, тесты, benchmark JSON, проверки чистого экспорта и submission, релизный отчёт, демо HTML. Числа относятся к публичной mock-среде и не предсказывают результат судейства.

LLM: фактическое поведение и live-проверка

llm_advisor.py передаёт модели до 40 агрегированных гипотез, параметры тарифов, каналов и доступные ресурсы. Строки клиентов, их ID, скрытые эффекты, seed и результаты evaluator в запрос не включаются. Модель может предложить до двух существующих гипотез для пилотов; она не заменяет измеренные эффекты и проверки лимитов. Если гипотезы уже выбраны, порядок пилотов сохраняется.

РежимПоведение
Обычный Agent()При наличии artifacts/llm_policy.json — офлайн-replay; при несовпадении контекста — численная политика. Без файла — off.
Agent({"llm_mode": "off"})Численная политика без применения LLM-рекомендаций.
Agent({"llm_mode": "assist"})До одного live-запроса на act; валидные рекомендации могут изменить выбор пилотов.
Agent({"llm_mode": "shadow"})Запрос и запись рекомендации без влияния на выбор пилотов.

Подстановка OPENAI_API_KEY сама по себе не включает live-режим обычного Agent(). Автоматический переход к API на изменённых данных в текущей версии не реализован. В live-режиме ключ читается из переменной окружения OPENAI_API_KEY, как требует ТЗ. Только явно запущенный CLI дополнительно загружает локальный .env; сам Agent() этого не делает.

Для локальной live-проверки после установки зависимостей:

# Создать шаблон только при отсутствии локального .env.
test -f .env || cp .env.example .env
chmod 600 .env
nano .env
# В редакторе заполнить OPENAI_API_KEY и сохранить файл.

python -m tools.llm_eval --check-config
python -m tools.llm_eval --mode assist --runs 1 --seed 42 \
  --output-dir "reports/llm_runs/live-check-$(date +%Y%m%d-%H%M%S)"

Ожидается api_key_configured: true, затем llm_status=ok и API requests: 1. Ключ не выводится и не должен попадать в Git. На судействе для явно включённого live-режима достаточно переменной окружения; файл .env не нужен.

Таймауты, ошибки API, отсутствующий ключ и невалидные ответы переводят агента на численную политику. CLI возвращает ненулевой код при неудачной live-проверке, даже если запасная политика завершилась успешно. Сохранённый ответ привязан к хешам публичного контекста и инструкций; устаревшие рекомендации отвергаются.

В релизной проверке выполнено 11 успешных реальных API-запросов, включая 10 сравнительных live-прогонов. Модель каждый раз выбрала гипотезы, уже входившие в численный план, поэтому результаты совпали с baseline. Рост прибыли от LLM на этом наборе не подтверждён. Ответы и расход токенов.

Есть сбор примеров и экспорт проверенной разметки для будущего обучения. Веса модели пока не обучались; сохранённая рекомендация не является обученной моделью. Настройка, обновление рекомендации для новых данных и подготовка обучающих примеров: LLM_INTEGRATION.md.

Архитектура и опциональные требования

Agent.act(env)
  -> generate_candidates(profile, history, tariffs)
  -> LLM-рекомендация: replay / явно включённый live / off
  -> run_adaptive_pilots(env, candidates)
  -> build_campaigns(env, observations)
  -> список финальных кампаний + last_trace
  • candidate_engine.py: устойчивое историческое ранжирование со shrinkage, разнообразием ячеек и каталожными альтернативами; до 40 гипотез по умолчанию.
  • llm_advisor.py: ограниченные рекомендации, валидация ответа, чтение сохранённой политики и безопасное поведение при ошибках API.
  • pilot_policy.py: до 10 разведочных SMS-пилотов по 80 контактов и до 5 адаптивно выбираемых подтверждений по 200. Оценки используют фактически возвращённые размеры выборок; отрицательные наблюдения сохраняются.
  • portfolio_optimizer.py: совместный выбор push/SMS/digital_ads, тарифа и пропуска ячейки при ограничениях бюджета и охвата. Не более одной финальной кампании на ячейку; до 5000 клиентов в порядке числового ID на кампанию.
  • agent.py: координация модулей, сброс trace на каждом запуске, контроль лимитов.
  • tools/benchmark.py и reporting.py: внешняя проверка и визуализация trace. Рендер отчёта не проводит новые пилоты и не меняет кампании.

Неопределённость учитывается через mean/SE/safe lift в нормализованных единицах; экономика применяет коэффициент канала один раз. Call исключён из-за насыщения конверсии. Выбор и число подтверждений зависят от измерений и ресурсов.

Дополнительный режим adaptive_confirmation_n=True подбирает также размер подтверждений по текущей неопределённости. В десяти прогонах его медиана составила 3,002,247.39, минимум — 1,305,074.91, положительных — 10/10. Он ухудшил минимум относительно основной политики, поэтому по умолчанию выключен.

Submission и состав сдачи

submission.csv генерируется неизменённым make_submission.py с seed 42. Публичные sanitize_campaigns и validate_strategy приняли все четыре кампании. Два запуска дали одинаковые байты; CSV соответствует сохранённому decision trace.

python make_submission.py
cp submission.csv /tmp/beeline-submission-first.csv
python make_submission.py
cmp submission.csv /tmp/beeline-submission-first.csv \
  && echo "OK: submission воспроизводится"
sha256sum submission.csv

Проверенный SHA-256:

3cba2865d369ad86c93e110476a4436c42f25c3583cbb9265382844e8e848e5e

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

В сдаваемую версию включены:

  • agent.py, candidate_engine.py, pilot_policy.py, portfolio_optimizer.py, llm_advisor.py и artifacts/llm_policy.json — модули и политика агента.
  • submission.csv, requirements.txt, README.md.
  • Для live-режима и проверки: requirements-llm.txt, requirements-dev.txt, tools/, tests/, reporting.py, docs/ и reports/.
  • Публичные CSV, data/ и неизменённые скрипты организаторов для локального воспроизведения. Сохраните структуру путей при передаче проекта.

.env, виртуальное окружение, кеши Python и локальные исходники в task/ не нужны для сдачи. API-ключ передавать в составе проекта нельзя.

Ограничения и целостность

Исторический before/after lift среди сменивших тариф не доказывает причинный эффект кампании. positive_rate не является конверсией, а prior_score — прогнозом прибыли. История и текущая аудитория в предоставленных данных не пересекаются по ID. На новой аудитории решения определяются её данными и пилотами.

После адаптивного отбора интервалы неопределённости являются эвристическими. Поиск ограниченной ширины не гарантирует глобальный оптимум. Точные ID пилотов недоступны агенту; оценки финального портфеля не изображают точную дедупликацию с пилотами. Фактический net gain считает официальный evaluator.

Когда нет положительной консервативной оценки, аварийная push-кампания явно помечается как рискованная: бесплатный контакт тоже может уменьшить выручку. Mock-эффекты отличаются от скрытой среды; результаты не являются прогнозом реального бизнеса или гарантией места на судействе.

Контрольные суммы подтверждают неизменность 15 файлов организаторов и данных. Дополнительные материалы: контракт, анализ данных, архитектура, демо.

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
15
Авторы
3
Файлы
104
Ветки
7

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

xretsam 7aitzhxn 6ayanamantay 2

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

  • 2026-09-23 17:57Finalize submission READMExretsam
  • 2026-09-23 17:35Finish verified LLM advice, deterministic replay, and adaptive sizing optionxretsam
  • 2026-09-23 17:17Prepare optional LLM exploration and reviewed training-data workflowxretsam
  • 2026-09-23 16:40Integrate final campaign agent and verify official release artifactsxretsam
  • 2026-09-23 16:33Add tariff campaign optimization agentaitzhxn
  • 2026-09-23 16:33Implement contract-compliant historical prior candidate enginexretsam
  • 2026-09-23 16:33Implement bounded campaign portfolio optimizeraitzhxn
  • 2026-09-23 16:33Add analyst report and portfolio documentationaitzhxn
Все коммиты (15)
  • 2026-09-23 16:26Implement contract-compliant historical prior candidate enginexretsam
  • 2026-09-23 16:05Add analyst report and portfolio documentationaitzhxn
  • 2026-09-23 16:03Implement bounded campaign portfolio optimizeraitzhxn
  • 2026-09-23 16:00Fix pilot resource accounting and preserve failure diagnosticsayanamantay
  • 2026-09-23 15:49Implement adaptive SMS pilots and tested integration handoffayanamantay
  • 2026-09-23 15:43Add tariff campaign optimization agentaitzhxn
  • 2026-09-23 14:49Add pilot-guided Beeline campaign agent and team architecturexretsam
Структура репозитория (104 файлов)
.env.example
.gitignore
PARTICIPANT_GUIDE.md
PARTICIPANT_GUIDE.pdf
PROMTS/00_START_HERE.md
PROMTS/01_STUDENT_PRIOR.md
PROMTS/03_STUDENT_PORTFOLIO.md
PROMTS/04_FINAL_INTEGRATION.md
PROMTS/SHARED_CONTRACT.md
README.md
agent.py
agent_template.py
artifacts/llm_policy.json
beeline_case_participants /ANALYSIS.md
beeline_case_participants /PARTICIPANT_GUIDE.md
beeline_case_participants /PARTICIPANT_GUIDE.pdf
beeline_case_participants /agent.py
beeline_case_participants /agent_template.py
beeline_case_participants /candidate_engine.py
beeline_case_participants /customer_profile.csv
beeline_case_participants /data/arpu_monthly.csv
beeline_case_participants /data/change_tariff.csv
beeline_case_participants /data/dict_tariff.csv
beeline_case_participants /data/traffic.csv
beeline_case_participants /environment.py
beeline_case_participants /feature_dictionary.csv
beeline_case_participants /local_eval.py
beeline_case_participants /make_submission.py
beeline_case_participants /mock_environment.py
beeline_case_participants /scoring_core.py
beeline_case_participants /submission.csv
beeline_case_participants /tariff_dictionary.csv
beeline_case_participants /test_candidate_engine.py
candidate_engine.py
customer_profile.csv
data/arpu_monthly.csv
data/change_tariff.csv
data/dict_tariff.csv
data/traffic.csv
docs/ARCHITECTURE.md
docs/DATA_FINDINGS.md
docs/DEMO.md
docs/LLM_INTEGRATION.md
environment.py
feature_dictionary.csv
llm_advisor.py
local_eval.py
make_submission.py
mock_environment.py
pilot_policy.py
portfolio_optimizer.py
reporting.py
reports/FINAL_RELEASE.md
reports/LLM_RELEASE.md
reports/benchmark.csv
reports/benchmark.json
reports/benchmark.md
reports/benchmark_integration_checklist.md
reports/benchmark_run.txt
reports/clean_checkout_tests.txt
reports/clean_checkout_verification.json
reports/data_audit.json
reports/decision_trace.json
reports/demo.html
reports/llm_clean_export_submission.txt
reports/llm_clean_export_tests.txt
reports/llm_final_10_seeds.txt
reports/llm_final_benchmark.log
reports/llm_final_seed42.txt
reports/llm_final_submission_first.txt
reports/llm_final_submission_second.txt
reports/llm_final_tests.txt
reports/llm_final_verification.json
reports/llm_live_evidence.json
reports/llm_preparation_10_seeds.txt
reports/llm_preparation_tests.txt
reports/llm_preparation_verification.json
reports/local_eval_10_seeds.txt
reports/local_eval_seed42.txt
reports/organizer_integrity.json
reports/submission_generation.txt
reports/submission_regeneration.txt
reports/submission_verification.json
reports/tests.txt
requirements-dev.txt
requirements-llm.txt
requirements.txt
scoring_core.py
submission.csv
tariff_dictionary.csv
tests/test_agent_integration.py
tests/test_candidate_engine.py
tests/test_llm_advisor.py
tests/test_llm_cli.py
tests/test_llm_replay.py
tests/test_pilot_policy.py
tests/test_portfolio_optimizer.py
tests/test_reporting.py
tests/test_training_data.py
tools/benchmark.py
tools/export_training_data.py
tools/freeze_llm_policy.py
tools/llm_eval.py
tools/profile_data.py
Ветки (7)

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

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

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