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

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

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

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

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

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

Реалізація AI-персоналізації рекомендацій в email-кампаніях

Середній Open Rate масових розсилок — 15-20%, CTR — 1-2%. Клієнти ігнорують нерелевантні пропозиції, відписуються, а LTV падає. Ручне сегментування за віком, статтю чи містом дає виграш у 5-10% до Open Rate, але цього недостатньо. Ми вирішуємо проблему за допомогою ML-персоналізації email-розсилок: кожен отримувач бачить лише ті товари, час і тему, які відповідають його поведінці. Це піднімає Open Rate до 35%, CTR до 8%, а Revenue per Email — у 4-5 разів. В одному проєкті для інтернет-магазину одягу ми підняли CTR з 1.2% до 7.8% за місяць — це в 6 разів. Колаборативна фільтрація — основа рекомендацій, а LLM генерує персоналізовані тексти.

Які проблеми вирішуємо?

  • Generic-теми на кшталт «Новинки місяця» не чіпляють. AI генерує індивідуальні заголовки, згадуючи ім'я клієнта або його останню покупку. Наприклад, «Олексію, ці кросівки Nike створені для тебе». Це підвищує Open Rate на 30-50%.
  • Якщо розсилати всім однакові товари, 60% отримувачів вважатимуть їх спамом. Персоналізовані рекомендації знижують відписки на 30-50% і збільшують CTR у 2-3 рази.
  • Відкриваність варіюється залежно від часового поясу та звичок. ML визначає оптимальну годину для кожного користувача, збільшуючи шанс прочитання до 40%. У результаті конверсія з листа зростає.

Як влаштована система?

В основі — гібридний підхід: колаборативна фільтрація для рекомендацій товарів + LLM (Claude 3.5 Sonnet) для генерації контенту. Стек: Python, Pandas, NumPy, Anthropic SDK. Ось як виглядає ядро:

import pandas as pd
import numpy as np
from anthropic import Anthropic
import json

class EmailPersonalizationEngine:
    def __init__(self, recommender, user_database):
        self.recommender = recommender  # Рекомендаційна система
        self.user_db = user_database
        self.llm = Anthropic()

    def generate_personalized_email(self, user_id: str,
                                     campaign_type: str,
                                     product_pool: list[dict]) -> dict:
        """Повністю персоналізований лист"""
        user = self.user_db.get_user(user_id)
        if not user:
            return self._generate_fallback_email(campaign_type, product_pool)

        # Персоналізовані товари
        user_recs = self.recommender.recommend(user_id, n=6)
        rec_ids = {r[0] for r in user_recs}

        # З пулу кампанії обираємо ті, що релевантні користувачеві
        personalized_products = [
            p for p in product_pool if p['id'] in rec_ids
        ][:3]

        # Якщо мало персоналізованих — додаємо популярні
        if len(personalized_products) < 3:
            popular = sorted(product_pool, key=lambda x: x.get('popularity', 0), reverse=True)
            personalized_products += [p for p in popular
                                       if p not in personalized_products][:3 - len(personalized_products)]

        # Персоналізована тема листа
        subject = self._generate_subject(user, personalized_products, campaign_type)

        # Персоналізований текст
        body_intro = self._generate_intro(user, personalized_products, campaign_type)

        # Оптимальний час відправлення
        send_time = self._optimal_send_time(user)

        return {
            'user_id': user_id,
            'subject': subject,
            'body_intro': body_intro,
            'products': personalized_products,
            'cta_text': self._get_cta_text(campaign_type, user),
            'send_at': send_time
        }

    def _generate_subject(self, user: dict, products: list,
                           campaign_type: str) -> str:
        """AI генерує персоналізовану тему"""
        product_names = [p.get('name', '') for p in products[:2]]
        top_category = products[0].get('category', '') if products else ''

        response = self.llm.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=80,
            messages=[{
                "role": "user",
                "content": f"""Write an email subject line (max 50 chars).

Customer: {user.get('first_name', 'Customer')}
Campaign: {campaign_type}
Featured: {', '.join(product_names)}
Top interest: {top_category}

Rules: personalize with name or interest, create curiosity, no spam words (FREE, !!!).
Return only the subject line."""
            }]
        )
        return response.content[0].text.strip()

    def _generate_intro(self, user: dict, products: list,
                         campaign_type: str) -> str:
        """Персоналізований вступний абзац"""
        user_context = f"""
First name: {user.get('first_name', 'Customer')}
Last purchase: {user.get('last_purchase_category', 'N/A')}
Member since: {user.get('member_months', 0)} months
Preferred brand: {user.get('top_brand', 'N/A')}
"""
        response = self.llm.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=100,
            messages=[{
                "role": "user",
                "content": f"""Write a 2-sentence personalized email intro.

User: {user_context}
Campaign: {campaign_type}
Products to highlight: {[p.get('name') for p in products[:2]]}

Be warm and personal. Reference past purchase or interest if relevant."""
            }]
        )
        return response.content[0].text

    def _optimal_send_time(self, user: dict) -> str:
        """Оптимальний час відправлення за патернами користувача"""
        # Історичні дані про час відкриттів
        open_hours = user.get('email_open_hours', [])

        if open_hours:
            # Знаходимо годину з максимальною кількістю відкриттів
            hour_counts = np.bincount(open_hours, minlength=24)
            best_hour = int(np.argmax(hour_counts))
        else:
            # Default: 10:00 ранку як найкращий час для більшості
            best_hour = 10

        # День тижня (якщо дані є)
        open_days = user.get('email_open_days', [])
        best_day = int(np.bincount(open_days, minlength=7).argmax()) if open_days else 2  # Tuesday default

        from datetime import datetime, timedelta
        today = datetime.now()
        days_until = (best_day - today.weekday()) % 7
        send_date = today + timedelta(days=days_until)
        return send_date.strftime(f"%Y-%m-%d {best_hour:02d}:00:00")

    def _get_cta_text(self, campaign_type: str, user: dict) -> str:
        cta_map = {
            'new_arrivals': 'Shop New Arrivals',
            'sale': f"Get Your {user.get('loyalty_tier', '').title()} Discount",
            'abandoned_cart': 'Complete Your Purchase',
            'reactivation': 'Discover What\'s New',
            'birthday': 'Claim Your Birthday Gift'
        }
        return cta_map.get(campaign_type, 'Shop Now')

    def _generate_fallback_email(self, campaign_type: str,
                                  product_pool: list[dict]) -> dict:
        """Не-персоналізований лист як fallback"""
        top_products = sorted(
            product_pool, key=lambda x: x.get('popularity', 0), reverse=True
        )[:3]
        return {
            'subject': 'Special picks just for you',
            'products': top_products,
            'cta_text': 'Shop Now'
        }

Batch-генерація для розсилки

    def generate_campaign_batch(self, user_ids: list,
                                  campaign_type: str,
                                  product_pool: list[dict]) -> pd.DataFrame:
        """Генерація листів для всієї бази"""
        results = []

        for user_id in user_ids:
            try:
                email = self.generate_personalized_email(
                    user_id, campaign_type, product_pool
                )
                results.append({'user_id': user_id, 'status': 'generated', **email})
            except Exception as e:
                results.append({'user_id': user_id, 'status': 'failed', 'error': str(e)})

        return pd.DataFrame(results)

Чому AI-персоналізація ефективніша за ручні сегменти?

Ручне сегментування (за віком, статтю, містом) дає виграш у 5-10% до Open Rate. AI-персоналізація враховує сотні факторів: історію покупок, час кліків, покинуті кошики, перегляди категорій. Наприклад, користувач, який переглядав кросівки Nike, отримає лист саме з ними, а не із загальним каталогом. В одному з проєктів для інтернет-магазину одягу ми підняли CTR з 1.2% до 7.8% за місяць — зростання в 6 разів. Згідно з документацією Anthropic, моделі сімейства Claude оптимізовані для генерації коротких продаючих текстів, що підвищує релевантність розсилки.

Порівняння: AI-персоналізація vs Generic-розсилки

Метрика Generic AI-персоналізація Покращення
Open Rate 15-20% 22-35% +50-100%
CTR 1-2% 3-8% +150-300%
Revenue per Email базовий зростання в 4-5 разів +300-500%
Відписки 0.5-1% 0.2-0.4% -50%

Важливі технічні обмеження: LLM-генерація 10K суб'єктів займає 15-30 хвилин, тому для великих баз потрібно попередньо генерувати шаблони. Ми використовуємо пайплайни з чергами для batch-обробки.

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

Етап Тривалість Результат
Аналітика 1-2 тижні Збір та очистка даних, побудова профілів користувачів
Проєктування 1 тиждень Вибір метрик, стеку (PyTorch, Hugging Face, Anthropic)
Розробка 2-4 тижні Код рекомендаційної системи та інтеграція з ESP
Тестування 1-2 тижні A/B-тест на 10% бази, вимірювання Open Rate та CTR
Деплой 1 тиждень Впровадження на повний обсяг, моніторинг

Типові помилки при впровадженні

  • Недостатність даних для холодного старту. Якщо у нових користувачів немає історії, рекомендації будуть неточними. Рішення — використовувати популярні товари як fallback і поступово збирати дані через A/B-тести.
  • Ігнорування часу відправлення. Навіть ідеальний лист не відкриють, якщо він прийшов о 3 годині ночі. ML-модель повинна враховувати часові зони та звички кожного клієнта.
  • Переоптимізація під CTR. Гонитва за кліками може призвести до агресивних CTA, які дратують користувачів. Важливо балансувати між залученням та довгостроковим LTV.

Що входить в роботу?

  • Аудит поточної email-стратегії — аналіз відкриваності, сегментів, контенту.
  • Розробка ML-моделі — підбір алгоритму рекомендацій та LLM для генерації контенту.
  • Інтеграція з CRM/ESP — API-з'єднання з вашою платформою розсилок (Mailchimp, SendPulse, власна).
  • A/B-тестування — порівняння персоналізованих листів з контрольною групою.
  • Документація та навчання — передача коду, інструкції для маркетологів, навчання команди.
  • Підтримка 3 місяці — моніторинг метрик, доналаштування моделей.

Ми займаємося AI-персоналізацією понад 5 років і реалізували 50+ проєктів для e-commerce, fintech та edtech. Гарантуємо підвищення Open Rate щонайменше на 20% – при невиконанні доналаштовуємо безкоштовно. Оцінимо ваш проєкт за 1-2 дні, отримайте консультацію та зв'яжіться з нами, щоб обговорити деталі.

Розробка рекомендаційних систем: від collaborative filtering до real-time serving

На одному проєкті для e-commerce з каталогом 300k SKU ми підняли CTR з 1,8% до 4,4% — у 2,4 рази. Перший ривок дала колаборативна фільтрація замість «популярне за останні 7 днів», другий — додавання контентних ознак та re-ranking. Різниця між «показуємо популярне» і «показуємо персоналізоване» — вимірна та суттєва. Нижче — інженерний досвід, який допоміг це зробити, і архітектури, які реально працюють у продакшені.

Collaborative Filtering: матрична факторизація та нейронні підходи

Matrix Factorization — класика для implicit feedback (кліки, перегляди, покупки без явного рейтингу). ALS (Alternating Least Squares) у бібліотеці Implicit обробляє матриці user×item із сотнями мільйонів ненульових значень за хвилини на GPU. Latent factors 64–256, регуляризація λ=0.01–0.1 — стартові параметри. Проблема cold start: для нового користувача або товару немає історії — класичний CF безпорадний, потрібні контентні ознаки або гібрид.

Neural Collaborative Filtering (NCF) замінює скалярний добуток на нейромережу. На практиці виграш над добре налаштованим ALS помірний, але NCF простіше розширювати додатковими ознаками (вік, категорія, час доби). Sequence-aware моделі (SASRec, BERT4Rec) враховують порядок взаємодій — state-of-the-art для сесійних рекомендацій.

Як вибрати архітектуру рекомендаційної системи?

Відповідь залежить від даних, навантаження та вимог до холодного старту. Нижче — три основні підходи з критеріями вибору.

Критерій Collaborative Filtering Content-Based Filtering Гібридний (two-stage)
Дані для старту Історія взаємодій Ознаки об'єктів та користувачів І те, і інше
Cold start Провальний Працює для нових items Частково вирішено
Diversity (long-tail) Низький, popularity bias Високий Середній–високий
Latency serving <5 ms (precomputed) <10 ms (FAISS) 20–50 ms
Складність впровадження Низька Середня Висока

Гібридна архітектура на 20–40% ефективніша за чистий CF за покриттям long-tail — перевірено на каталогах від 100k SKU.

Content-Based Filtering: коли історії взаємодій мало

Content-based рекомендує на основі характеристик товарів, а не поведінки інших користувачів — вирішує cold start для нових items. Текстові ембединги через sentence-transformers (multilingual-e5-base, BGE-M3) → пошук схожих через FAISS IndexFlatIP — запит за <5 ms на 100k товарів. Item2Vec (Word2Vec на послідовностях переглядів) дає інтерпретовані «схожі товари» за пару годин навчання.

Структуровані ознаки (категорія, бренд, ціна) подаються через embedding layers або в gradient boosting — CatBoost працює з категоріями без ручного кодування.

Чому гібридні моделі працюють краще?

Production-системи майже завжди дворівневі. Stage 1 (Retrieval) — швидкий відбір 100–500 кандидатів із 300k товарів через ALS або Two-Tower модель з векторним пошуком (FAISS, Qdrant). Stage 2 (Ranking) — важкий ранжувальник на LightGBM або нейромережі з cross-features, часом, пристроєм та контекстом сесії. LightFM — хороша відправна точка для середнього масштабу без важкої інфраструктури. Наша практика показує: перехід від single-stage до two-stage дає приріст точності на 15–25% при зростанні latency всього на 20–30 мс.

Real-Time Serving: архітектура під навантаження

Latency SLA — 50–100 ms при тисячах запитів на секунду. Base-рекомендації precompute (batch job раз на годину) → Redis по user_id → <5 ms. Real-time re-ranking через Kafka для подій (кліки, додавання в кошик) → оновлення контекстних ознак. Feature serving — Redis з TTL (кількість переглядів за 24 години, останній клікнутий item). При навантаженні 10k req/s ставимо Redis Cluster з реплікацією.

A/B тестування — єдиний достовірний спосіб оцінити покращення. Офлайн-метрики корелюють з онлайн не завжди. Kohavi et al., «Online Controlled Experiments at Large Scale» (KDD 2013) — обов'язкове читання для команди. Тест з 5–10% трафіку, моніторинг CTR, конверсії, revenue per session. Одна з наших клієнтських систем після гібридизації збільшила виручку на 18% за місяць A/B.

Терміни розробки рекомендаційної системи

Етапи та типові часові витрати — у таблиці нижче. Вартість розраховується індивідуально під масштаб каталогу та вимоги до latency.

Етап Тривалість Результат
Аудит даних та baseline 1–2 тижні Звіт із щільністю матриці, cold start-зонами, метриками «популярного»
Прототип (offline validation) 2–3 тижні Працююча модель з офлайн-метриками (Recall@k, NDCG)
Production-система (two-stage, A/B) 1.5–2.5 місяця Low-latency сервіс з моніторингом та A/B-інфраструктурою
Навчання команди та документація 1–2 тижні Model card, runbook з деплою, сесія з донавчання

Що входить у розробку під ключ

  1. Аудит даних — щільність матриці user×item (зазвичай <0,1%), розподіл активності, temporal паттерни, cold start статистика.
  2. Baseline — «популярне» як простий поріг, який часто важко перевершити.
  3. Ітеративне покращення — ALS → контентні ознаки → two-stage → sequence-aware. Кожен крок з A/B.
  4. Інфраструктура serving — batch precomputation, Redis, real-time re-ranking, моніторинг у Grafana.
  5. Документація — model card з метриками, інструкція з деплою, опис ознак.
  6. Навчання команди — сесія з інтерпретації результатів та донавчання моделі.
  7. Підтримка — 1 місяць після запуску (фікс інцидентів, доналаштування pipeline).

Ми — команда з 7+ роками досвіду в рекомендаційних системах, реалізували понад 30 проєктів для e-commerce та медіа. Гарантуємо прозоре A/B-тестування та фіксацію покращення метрик.

Хочете оцінити потенціал зростання вашого каталогу? Зв'яжіться з нами для безкоштовного аудиту даних. Замовте розробку рекомендаційної системи — перший прототип протягом двох тижнів.

Приклад конфігу ALS для implicit feedback
from implicit.als import AlternatingLeastSquares

model = AlternatingLeastSquares(
    factors=64,
    regularization=0.05,
    iterations=15,
    use_gpu=True
)
model.fit(user_item_matrix)

Більше про математику рекомендаційних систем — у Wikipedia.