Розробка AI-системи рекомендацій Cross-Sell для продажів

Реалізація AI-системи рекомендацій Cross-Sell для продажів

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

Часті запитання

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

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

Реалізація AI-системи рекомендацій Cross-Sell для продажів

До нас звернувся e-commerce-проєкт із 50 000 SKU: правило «до принтера — картридж» давало лише 8% конверсії. Потрібна була рекомендаційна система на основі машинного навчання, яка знаходить неочевидні пари та адаптується під поведінку кожного клієнта. Ми реалізували гібридну систему для e-commerce та ритейлу: асоціативні правила для базових зв’язок + градієнтний бустинг для персоналізації. Результат — зростання середнього чека на 18% за перший місяць, що забезпечило значний приріст виручки. Розповідаю, як це працює.

Проблеми, які вирішуємо

Статичні правила не бачать прихованих закономірностей. Наприклад, клієнти, які купили дитяче автокрісло, з імовірністю 22% придбають органайзер для багажника — хоча товари з різних категорій. ML знаходить такі патерни через асоціативні правила (Lift > 2.0). А персоналізація через градієнтний бустинг враховує історію клієнта: якщо користувач уже брав органайзер, рекомендація зміщується на інший товар.

Інша типова проблема — товари з коротким циклом споживання (розхідники, підписки). Тут потрібне передбачення наступної покупки. Модель на основі розподілу інтервалів видає товари, які клієнт ось-ось замовить знову. Так ми збільшуємо повторні продажі без промоакцій.

Третя проблема — холодний старт для нових товарів. Якщо товар не має історії покупок, правила Apriori не спрацюють. Рішення — використовувати content-based ознаки (категорія, ціна, бренд) та колаборативну фільтрацію через ембеддінги. Для цього ми збагачуємо модель градієнтного бустингу фічами товару.

Як ми будуємо модель CrossSellRecommender

Market Basket Analysis + персоналізація

Гібридна архітектура: спочатку Apriori дає сирі правила, потім градієнтний бустинг ранжує кандидатів під конкретного користувача. Це поєднання забезпечує lift конверсії в 3 рази вищий, ніж rule-based підхід.

import pandas as pd import numpy as np from mlxtend.frequent_patterns import apriori, association_rules from mlxtend.preprocessing import TransactionEncoder from sklearn.ensemble import GradientBoostingClassifier class CrossSellRecommender: def __init__(self, min_support: float = 0.01, min_confidence: float = 0.1): self.min_support = min_support self.min_confidence = min_confidence self.rules = None self.cross_sell_map = {} self.personalization_model = None def fit_association_rules(self, orders_df: pd.DataFrame, order_col: str = "order_id", item_col: str = "item_id"): """Пошук асоціативних правил через Apriori""" # Кошики транзакцій baskets = orders_df.groupby(order_col)[item_col].apply(list).tolist() te = TransactionEncoder() te_array = te.fit_transform(baskets) df_encoded = pd.DataFrame(te_array, columns=te.columns_) # Часті набори frequent_itemsets = apriori( df_encoded, min_support=self.min_support, use_colnames=True, max_len=3 ) # Правила асоціації self.rules = association_rules( frequent_itemsets, metric="lift", min_threshold=1.2 ) self.rules = self.rules[self.rules['confidence'] >= self.min_confidence] self.rules = self.rules.sort_values('lift', ascending=False) # Маппінг: item → список рекомендацій з метриками for _, rule in self.rules.iterrows(): for antecedent in rule['antecedents']: if antecedent not in self.cross_sell_map: self.cross_sell_map[antecedent] = [] for consequent in rule['consequents']: if antecedent != consequent: self.cross_sell_map[antecedent].append({ 'item_id': consequent, 'confidence': rule['confidence'], 'lift': rule['lift'], 'support': rule['support'] }) # Сортування за lift for item in self.cross_sell_map: self.cross_sell_map[item].sort(key=lambda x: x['lift'], reverse=True) def recommend_cross_sell(self, cart_items: list[str], user_history: list[str] = None, n: int = 5) -> list[dict]: """Cross-sell для поточного кошика""" candidates = {} for item_id in cart_items: related = self.cross_sell_map.get(item_id, []) for rec in related: rec_id = rec['item_id'] # Пропускаємо вже в кошику або в історії if rec_id in cart_items: continue if user_history and rec_id in user_history: continue if rec_id not in candidates: candidates[rec_id] = {'score': 0, 'triggers': []} candidates[rec_id]['score'] += rec['lift'] candidates[rec_id]['triggers'].append(item_id) # Нормалізація if not candidates: return [] sorted_candidates = sorted( [{'item_id': k, **v} for k, v in candidates.items()], key=lambda x: x['score'], reverse=True ) return sorted_candidates[:n] def get_complementary_categories(self, category: str) -> list[str]: """Взаємодоповнюючі категорії""" category_rules = self.rules[ self.rules['antecedents'].apply(lambda x: category in str(x)) ]['consequents'].apply(lambda x: list(x)).explode().value_counts() return category_rules.head(5).index.tolist() 

Часові патерни: наступне замовлення

class NextPurchasePredictor: """Передбачення наступної покупки на основі історії""" def predict_next_items(self, user_id: str, purchase_history: list[dict], catalog_features: pd.DataFrame) -> list[tuple]: """ purchase_history: [{item_id, date, quantity, category}] Повертає: [(item_id, probability)] """ if len(purchase_history) < 3: return [] # Патерн повторних покупок item_intervals = {} for i in range(1, len(purchase_history)): item = purchase_history[i]['item_id'] prev_same = [h for h in purchase_history[:i] if h['item_id'] == item] if prev_same: days_between = ( pd.to_datetime(purchase_history[i]['date']) - pd.to_datetime(prev_same[-1]['date']) ).days if item not in item_intervals: item_intervals[item] = [] item_intervals[item].append(days_between) # Передбачення повторних покупок predictions = [] last_purchase_date = pd.to_datetime(purchase_history[-1]['date']) today = pd.Timestamp.now() days_since_last = (today - last_purchase_date).days for item_id, intervals in item_intervals.items(): avg_interval = np.mean(intervals) std_interval = np.std(intervals) if len(intervals) > 1 else avg_interval * 0.3 # Ймовірність через normal distribution from scipy.stats import norm prob = norm.cdf(days_since_last + 7, avg_interval, std_interval + 1) prob -= norm.cdf(days_since_last - 7, avg_interval, std_interval + 1) prob = min(max(prob, 0), 1) if prob > 0.1: predictions.append((item_id, prob)) return sorted(predictions, key=lambda x: x[1], reverse=True)[:10] 
Докладніше про налаштування Apriori

Association rules з min_support=0.01, min_confidence=0.1 зазвичай дають 500-5000 значущих правил на 100K замовлень. Lift > 2.0 — сильна асоціація. Для підбору гіперпараметрів використовуємо крос-валідацію: розбиваємо дані за часом (train/test) і обираємо min_support, min_confidence за максимальним lift на валідаційній вибірці.

Як навчити модель CrossSellRecommender на своїх даних

  1. Підготовка даних. Зберіть історію замовлень з колонками: order_id, item_id, date. Мінімальна кількість транзакцій — 10 000.
  2. Запустіть Apriori. Використовуйте метод fit_association_rules з min_support=0.01 та min_confidence=0.1. Це дасть ~1000 правил.
  3. Налаштуйте параметри. Перевірте розподіл lift і confidence. Якщо правил забагато, збільште min_support до 0.02 або min_confidence до 0.2.
  4. Оцініть якість. Використовуйте метрики precision@k та recall@k на відкладеній вибірці. Cross-sell через правила дає середній uplift кошика 15-25%. Комбінація з персоналізацією (історія користувача) додає ще 5-10% до acceptance rate.

Як виміряти якість рекомендацій?

Основні offline-метрики: precision@k, recall@k, lift@k. Ми використовуємо усічений кошик — приховуємо частину товарів з кожної транзакції та перевіряємо, чи потрапляють вони в рекомендації. Онлайн-метрики — acceptance rate, AOV uplift, частка кошиків з cross-sell. На A/B-тесті з 50% аудиторії типовий uplift acceptance rate становить 10-25%.

Чому гібридна модель ефективніша за rule-based?

Rule-based (наприклад, "купив А — покажи Б") не масштабується на тисячі товарів: правила стають розрідженими і не враховують контекст. ML знаходить асоціації з високим lift навіть для рідкісних пар. Крім того, гібрид персоналізує ранжування: один і той самий товар ранжується по-різному для різних користувачів. У наших проєктах acceptance rate гібрида в 3 рази вищий, ніж у правил.

Етапи впровадження

Етап Що робимо Результат Тривалість
1. Аудит даних Перевіряємо повноту та якість: кількість SKU, довжину історії, частоту замовлень Дашборд метрик, список пропусків 1-2 дні
2. Побудова пайплайну ETL для збору даних з CRM, очищення, агрегація кошиків Датасет orders_df 3-4 дні
3. Навчання правил Apriori, підбір min_support та min_confidence через крос-валідацію Файл правил (.pkl) 1-2 дні
4. Персоналізація Навчаємо градієнтний бустинг на історії користувачів Ранжуюча модель 3-5 днів
5. A/B-тест 50% аудиторії — стара система, 50% — нова. Рахуємо конверсію та AOV Звіт з uplift 7-14 днів
6. Продакшн-деплой Інтеграція через REST API, моніторинг latency p99 Документація, дашборд 2-3 дні

Що входить в результат

  • Документація: опис правил, метрик, інструкція для оновлення моделі.
  • Вихідний код: репозиторій з модулями CrossSellRecommender, NextPurchasePredictor, конфіги та тести.
  • API-ендпоінти: два методи — recommend_by_cart (за поточним кошиком) та recommend_by_user (за історією).
  • Навчання команди: показуємо, як інтерпретувати результати та донавчати модель.
  • Гарантія: ми супроводжуємо A/B-тест до досягнення статистично значущого uplift.

Як оцінити ROI для вашого бізнесу

Метрика Типове значення Як розраховуємо
Приріст середнього чека 15-25% (AOV_тест - AOV_контроль) / AOV_контроль * 100%
Acceptance rate 5-12% Кліки за рекомендаціями / покази
Частка кошиків з cross-sell 30-50% Кошики з ≥1 рекомендованим товаром / всього кошиків
Час окупності 2-4 місяці Вартість впровадження / щомісячний приріст виручки

Щоб оцінити потенціал cross-sell для вашого асортименту, зв'яжіться з нами. Ми проведемо аудит даних і надамо прототип за 2 тижні з гарантією конфіденційності. Замовте консультацію — обговоримо деталі вашого проєкту та підготуємо індивідуальну пропозицію.