Розробка AI-системи реактивації неактивних клієнтів

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка AI-системи реактивації неактивних клієнтів
Середній
~1-2 тижні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Впровадження AI-системи реактивації неактивних клієнтів

Реактивація "сплячих" клієнтів коштує у 5-7 разів дешевше, ніж залучення нових. AI-система визначає оптимальний момент реактивації, сегментує неактивних за причиною відтоку та формує персоналізовану пропозицію для кожного сегменту.

Модель сегментації неактивних клієнтів

import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from anthropic import Anthropic

class InactiveCustomerAnalyzer:
    def __init__(self, inactivity_threshold_days: int = 90):
        self.threshold = inactivity_threshold_days
        self.llm = Anthropic()
        self.scaler = StandardScaler()

    def identify_inactive(self, customers_df: pd.DataFrame,
                           last_activity_col: str = 'last_purchase_date') -> pd.DataFrame:
        """Визначення неактивних клієнтів"""
        customers_df['days_inactive'] = (
            pd.Timestamp.now() -
            pd.to_datetime(customers_df[last_activity_col])
        ).dt.days

        inactive = customers_df[
            customers_df['days_inactive'] >= self.threshold
        ].copy()

        return inactive

    def segment_inactive(self, inactive_df: pd.DataFrame) -> pd.DataFrame:
        """Кластеризація неактивних за поведінковою схемою"""
        features = pd.DataFrame()

        features['days_inactive'] = inactive_df['days_inactive']
        features['total_orders'] = inactive_df.get('total_orders', 1)
        features['avg_order_value'] = inactive_df.get('avg_order_value', 0)
        features['order_frequency'] = inactive_df.get('order_frequency', 0)
        features['last_order_value'] = inactive_df.get('last_order_value', 0)
        features['support_issues'] = inactive_df.get('support_tickets_total', 0)

        X = self.scaler.fit_transform(features.fillna(0))

        km = KMeans(n_clusters=5, random_state=42, n_init=10)
        inactive_df['segment'] = km.fit_predict(X)

        # Описи сегментів
        segment_profiles = features.copy()
        segment_profiles['segment'] = inactive_df['segment']
        segment_stats = segment_profiles.groupby('segment').mean()

        # LLM називає кожен сегмент
        for seg_id in range(5):
            if seg_id not in segment_stats.index:
                continue
            stats = segment_stats.loc[seg_id].to_dict()
            stats_str = ", ".join([f"{k}: {v:.1f}" for k, v in stats.items()])

            response = self.llm.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=100,
                messages=[{
                    "role": "user",
                    "content": f"""Name this inactive customer segment (3-5 words) and suggest reactivation approach.

Stats: {stats_str}

Return: "Segment Name | 1-sentence strategy" """
                }]
            )
            print(f"Segment {seg_id}: {response.content[0].text}")

        return inactive_df


class ReactivationCampaign:
    """Кампанія реактивації з персоналізацією"""

    def __init__(self):
        self.llm = Anthropic()
        self.reactivation_offers = {
            0: {'discount': 20, 'message_theme': 'we_miss_you'},
            1: {'discount': 15, 'message_theme': 'best_of_what_they_liked'},
            2: {'discount': 10, 'free_shipping': True, 'message_theme': 'new_arrivals'},
            3: {'special_access': True, 'message_theme': 'exclusive_comeback'},
            4: {'survey': True, 'small_incentive': True, 'message_theme': 'help_us_improve'},
        }

    def create_reactivation_email(self, user: dict, segment: int) -> dict:
        """Персоналізований лист реактивації"""
        offer = self.reactivation_offers.get(segment, {'discount': 10})
        days_inactive = user.get('days_inactive', 90)
        past_categories = user.get('top_categories', ['products'])

        response = self.llm.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=300,
            messages=[{
                "role": "user",
                "content": f"""Write a reactivation email for an inactive customer.

Customer: {user.get('first_name', 'Customer')}
Inactive for: {days_inactive} days
Past purchases: {', '.join(past_categories[:3])}
Offer: {offer}

Requirements:
- Subject line (engaging, personal, 50 chars max)
- Body (150 words max, warm tone, mention specific past interest)
- Clear CTA

Return JSON: {{"subject": "...", "body": "...", "cta": "..."}}"""
            }]
        )

        try:
            import json
            return json.loads(response.content[0].text)
        except Exception:
            return {'subject': f"We miss you, {user.get('first_name', '')}!",
                    'body': response.content[0].text[:400], 'cta': 'Come Back'}

    def predict_reactivation_probability(self, user: dict,
                                          offer: dict) -> float:
        """Ймовірність реактивації з певною пропозицією"""
        # Спрощена евристика (у реальності — навчена модель)
        base_prob = 0.05  # Базова ймовірність

        # Фактори, що підвищують ймовірність
        if user.get('total_orders', 0) > 5:
            base_prob += 0.05  # Лояльний клієнт
        if user.get('days_inactive', 999) < 180:
            base_prob += 0.08  # Нещодавно пішов
        if offer.get('discount', 0) >= 20:
            base_prob += 0.06  # Хороша знижка
        if user.get('email_open_rate', 0) > 0.3:
            base_prob += 0.04  # Відкриває листи

        return min(base_prob, 0.4)

Типична конверсія кампанії реактивації: 5-15% залежно від давності неактивності та якості персоналізації. Оптимальні часові вікна: 90-180 днів неактивності (найкращий рівень відповідей), 180-365 днів (потрібна сильніша мотивація), > 365 днів (зазвичай дешевше вважати відтоком). Рекомендується 1-2 листи з інтервалом 7-14 днів, потім припинити.