Разработка AI-системы для персонализации промоакций

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Разработка AI-системы для персонализации промоакций
Средняя
~1-2 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1240
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    867
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1084
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    829

Реализация AI-системы персонализации промо-акций

Промо-персонализация — определение, кому, какую скидку и в какой момент предложить. Массовые скидки "всем 15%" — деньги на ветер: 30-40% получателей купили бы без скидки. ML-система предлагает скидку только тем, кто в ней нуждается, и подбирает минимальный стимул, достаточный для конверсии.

Модель uplift для промо

import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import cross_val_score

class PromoUpliftModel:
    """
    Uplift modeling: предсказывает не вероятность покупки,
    а ПРИРОСТ вероятности от скидки.
    """

    def __init__(self):
        # Two-model approach
        self.model_treatment = GradientBoostingClassifier(
            n_estimators=200, learning_rate=0.05, random_state=42
        )
        self.model_control = GradientBoostingClassifier(
            n_estimators=200, learning_rate=0.05, random_state=42
        )

    def train(self, df: pd.DataFrame, feature_cols: list):
        """
        df: user_id, received_promo (0/1), purchased (0/1), features...
        """
        X = df[feature_cols].fillna(0)
        y = df['purchased']

        # Обучаем отдельно на тех, кто получил промо, и кто не получил
        treatment_mask = df['received_promo'] == 1
        control_mask = df['received_promo'] == 0

        X_t, y_t = X[treatment_mask], y[treatment_mask]
        X_c, y_c = X[control_mask], y[control_mask]

        self.model_treatment.fit(X_t, y_t)
        self.model_control.fit(X_c, y_c)

        print(f"Treatment model AUC: {cross_val_score(self.model_treatment, X_t, y_t, scoring='roc_auc', cv=3).mean():.3f}")
        print(f"Control model AUC: {cross_val_score(self.model_control, X_c, y_c, scoring='roc_auc', cv=3).mean():.3f}")

    def predict_uplift(self, X: pd.DataFrame) -> pd.Series:
        """Предсказание uplift для каждого пользователя"""
        p_treatment = self.model_treatment.predict_proba(X)[:, 1]
        p_control = self.model_control.predict_proba(X)[:, 1]
        return pd.Series(p_treatment - p_control, index=X.index)


class PromoPersonalizationEngine:
    def __init__(self, uplift_model: PromoUpliftModel):
        self.uplift_model = uplift_model
        self.promo_tiers = [
            {'discount': 5, 'min_uplift': 0.05},
            {'discount': 10, 'min_uplift': 0.04},
            {'discount': 15, 'min_uplift': 0.03},
            {'discount': 20, 'min_uplift': 0.025},
            {'discount': 25, 'min_uplift': 0.02},
        ]

    def assign_promo(self, users_df: pd.DataFrame,
                      feature_cols: list,
                      budget_per_user: float = 50) -> pd.DataFrame:
        """Персональное назначение промо-скидок"""
        X = users_df[feature_cols].fillna(0)
        uplifts = self.uplift_model.predict_uplift(X)

        result = users_df[['user_id']].copy()
        result['predicted_uplift'] = uplifts.values
        result['segment'] = 'no_promo'
        result['discount_pct'] = 0
        result['expected_roi'] = 0

        for _, row in result.iterrows():
            idx = row.name
            uplift = result.at[idx, 'predicted_uplift']
            avg_order = users_df.at[idx, 'avg_order_value'] if 'avg_order_value' in users_df.columns else 100

            # Выбираем минимальную скидку с положительным ROI
            for tier in self.promo_tiers:
                if uplift >= tier['min_uplift']:
                    promo_cost = avg_order * tier['discount'] / 100
                    expected_revenue_lift = uplift * avg_order
                    roi = (expected_revenue_lift - promo_cost) / promo_cost

                    if roi > 0.5 and promo_cost <= budget_per_user:
                        result.at[idx, 'discount_pct'] = tier['discount']
                        result.at[idx, 'expected_roi'] = roi

                        # Сегментация
                        if uplift > 0.15:
                            result.at[idx, 'segment'] = 'persuadable_high'
                        elif uplift > 0.07:
                            result.at[idx, 'segment'] = 'persuadable_low'
                        else:
                            result.at[idx, 'segment'] = 'sure_thing'
                        break

        return result

    def calculate_promo_roi(self, results_df: pd.DataFrame) -> dict:
        """Расчёт ROI промо-кампании"""
        with_promo = results_df[results_df['discount_pct'] > 0]
        without_promo = results_df[results_df['discount_pct'] == 0]

        return {
            'total_users_targeted': len(with_promo),
            'avg_discount': with_promo['discount_pct'].mean(),
            'estimated_total_cost': (with_promo['discount_pct'] / 100 * 100).sum(),
            'segment_breakdown': results_df['segment'].value_counts().to_dict(),
            'expected_avg_roi': with_promo['expected_roi'].mean()
        }

Uplift modeling экономит 25-40% промо-бюджета против "скидки всем". Ключевые сегменты:

  • Sure Things (~20%) — купят без скидки: не трогаем
  • Persuadables (~35%) — нужен правильный стимул: таргетируем
  • Lost Causes (~25%) — не купят даже со скидкой: не тратим бюджет
  • Sleeping Dogs (~20%) — скидка их раздражает: не трогаем

Правильная сегментация по uplift типично сохраняет 40-50% промо-бюджета при сохранении 85-90% объёма продаж.