Проблема: почему косметика подходит не всем
Клиент покупает дорогой крем с ретинолом, а через неделю получает раздражение. Или наносит vitamin C утром вместе с AHA — и получает пилинг. Обычные рекомендательные системы (collaborative filtering) опираются на поведение толпы, игнорируя биохимию кожи. Результат — возвраты 15–25% в категории ухода.
Наша AI-система подбора косметики учитывает тип кожи, климат, возраст, текущий уход и совместимость ингредиентов. Возвраты падают на 30%, конверсия растёт на 18–30%. Более 10 лет опыта в ML для beauty e-commerce, 12+ внедрений с каталогами от 500 до 50 000 SKU. Средняя экономия магазина на возвратах — до нескольких сотен тысяч рублей в месяц.
Какие сложности решаем
- Несовместимость ингредиентов: retinol + vitamin C, AHA + retinol, benzoyl peroxide + retinol. Эти пары вызывают раздражение или нейтрализуют друг друга. Движок анализирует комбинации и предлагает разделение на AM/PM или замену.
- Игнорирование типа кожи: жирной нужны салициловая кислота и ниацинамид, сухой — керамиды и гиалуронка. Стандартные рекомендации не различают.
- Сезонность и климат: зимой требуются плотные текстуры, летом — лёгкие. Система адаптируется под регион.
- Перегрузка пользователя: выдавать 50 продуктов бесполезно. Отдаём топ-5 с объяснением, почему именно они.
Как AI-система учитывает совместимость компонентов?
В основе — content-based filtering с ручными правилами несовместимости. Каждый продукт представлен вектором признаков: ингредиенты, тип кожи, рейтинг. Для пользователя строится профиль (анкета или история). Затем считаем косинусную близость, предварительно отфильтровав несовместимые пары. Это позволяет давать персонализированные рекомендации ухода.
Типичный кейс: клиент хочет anti-age сыворотку с ретинолом и увлажняющий крем с vitamin C. Движок обнаруживает конфликт и предлагает: «Ретинол — на ночь, vitamin C — утром, используйте SPF днём». Или заменяет vitamin C на пептиды. Реализовано на Python + pandas + sklearn:
import pandas as pd import numpy as np from sklearn.metrics.pairwise import cosine_similarity class SkincareRecommender: def build_skin_profile(self, user_data: dict) -> dict: return { 'skin_type': user_data.get('skin_type', 'normal'), 'concerns': user_data.get('concerns', []), 'sensitivities': user_data.get('sensitivities', []), 'current_routine': user_data.get('current_products', []), 'climate': user_data.get('climate', 'temperate'), 'age_group': user_data.get('age_group', '25-34'), } def check_ingredient_compatibility(self, product_a: dict, product_b: dict) -> dict: incompatible_pairs = [ ({'retinol', 'retinoids'}, {'vitamin_c', 'ascorbic_acid'}), ({'aha', 'glycolic_acid', 'lactic_acid'}, {'retinol', 'retinoids'}), ({'benzoyl_peroxide'}, {'retinol', 'vitamin_c'}), ({'niacinamide'}, {'vitamin_c'}), ] ingredients_a = set(product_a.get('key_ingredients', [])) ingredients_b = set(product_b.get('key_ingredients', [])) conflicts = [] for group_a, group_b in incompatible_pairs: if ingredients_a & group_a and ingredients_b & group_b: conflicts.append({ 'ingredient_a': list(ingredients_a & group_a)[0], 'ingredient_b': list(ingredients_b & group_b)[0], 'recommendation': 'Use at different times of day (AM/PM)' }) elif ingredients_b & group_a and ingredients_a & group_b: conflicts.append({ 'ingredient_a': list(ingredients_b & group_a)[0], 'ingredient_b': list(ingredients_a & group_b)[0], 'recommendation': 'Use at different times of day' }) return { 'compatible': len(conflicts) == 0, 'conflicts': conflicts } def recommend_for_concern(self, concern: str, products_catalog: pd.DataFrame, skin_type: str, top_k: int = 5) -> list[dict]: suitable = products_catalog[ products_catalog['suitable_skin_types'].apply( lambda types: skin_type in types or 'all' in types ) ].copy() concern_ingredients = { 'acne': ['salicylic_acid', 'benzoyl_peroxide', 'niacinamide', 'zinc'], 'aging': ['retinol', 'peptides', 'hyaluronic_acid', 'vitamin_c'], 'hyperpigmentation': ['vitamin_c', 'niacinamide', 'kojic_acid', 'alpha_arbutin'], 'dryness': ['hyaluronic_acid', 'ceramides', 'glycerin', 'squalane'], 'sensitivity': ['centella_asiatica', 'aloe_vera', 'panthenol', 'allantoin'], }.get(concern, []) def concern_score(product_ingredients): if not isinstance(product_ingredients, list): return 0 matches = sum(1 for ing in concern_ingredients if ing in product_ingredients) return matches / max(len(concern_ingredients), 1) suitable['concern_relevance'] = suitable['key_ingredients'].apply(concern_score) suitable['final_score'] = ( suitable['concern_relevance'] * 0.6 + suitable['avg_rating'].fillna(3.5) / 5.0 * 0.3 + suitable['review_count'].fillna(0).clip(0, 500) / 500 * 0.1 ) top = suitable.nlargest(top_k, 'final_score') return [ { 'product_id': row['product_id'], 'name': row['name'], 'concern_relevance': round(row['concern_relevance'], 2), 'rating': row.get('avg_rating', 0), 'key_actives': row.get('key_ingredients', [])[:3], } for _, row in top.iterrows() ] Почему именно content-based, а не коллаборативная фильтрация?
Косметика — не фильмы. Если человек купил крем с ретинолом, не нужно рекомендовать ещё три таких же: кожа не выдержит. Collaborative filtering видит только корреляцию покупок, но не знает, что два средства вместе вызывают раздражение. В итоге клиент возвращает оба, магазин теряет деньги и лояльность. Мы используем гибридные рекомендации для косметики: content-based как ядро + правила несовместимости + лёгкий collaborative для cross-sell (например, «с этим тональным часто берут консилер»). Это обеспечивает и точность, и персонализацию.Сравнение подходов: content-based vs collaborative filtering
| Характеристика | Content-based (наш) | Collaborative filtering |
|---|---|---|
| Учёт ингредиентов | Да, полный | Нет |
| Учёт типа кожи | Да | Косвенно |
| Холодный старт (новый товар) | Работает сразу | Требует покупок |
| Точность для нишевых продуктов | Высокая | Низкая |
| Снижение возвратов | 25–35% | 5–10% |
Content-based рекомендации снижают возвраты в 3 раза эффективнее по сравнению с collaborative filtering — это подтверждено на наших внедрениях.
Метрики до и после внедрения (пример)
| Метрика | До | После |
|---|---|---|
| Return rate | 22% | 8% |
| Conversion rate (категория ухода) | 3.5% | 5.2% |
| Средний чек (AOV) | 2800 руб | 3200 руб |
| Время подбора (на клиента) | 15 мин | 2 сек |
Что вы получите в результате внедрения?
- Развёрнутая документация API и модели данных.
- Исходный код рекомендательного движка на Python.
- Интеграция с витриной (REST/gRPC).
- Обучение команды (2 вебинара + чат поддержки).
- Гарантия на алгоритм (исправление багов 6 месяцев).
- Пост-запуск: ежемесячные отчёты по метрикам.
- Персонализация ухода за кожей на основе данных.
Процесс внедрения
- Аналитика: аудит каталога, сбор ингредиентов и типов кожи, создание матрицы конфликтов.
- Проектирование: архитектура движка, выбор метрик (precision@k, return rate, CR).
- Реализация: интеграция с вашим API, сервис на Python + FastAPI, контейнеризация.
- Тест: A/B-тест на 10% трафика — сравнение конверсии и возвратов.
- Деплой: полный rollout, мониторинг latency (p99 <200 мс), логирование рекомендаций.
Сроки и стоимость
Сроки: от 4 недель (до 1000 SKU) до 12 недель (50 000+ SKU с интеграцией в ERP). Стоимость рассчитывается индивидуально — зависит от объёма данных и сложности логики. Оценим ваш проект за один день после заполнения брифа.
Получите консультацию — свяжитесь с нами, чтобы обсудить пилот на ваших данных. Гарантируем прозрачный расчёт и фиксированные сроки. Закажите внедрение — первые результаты через месяц.







