Проблема: чому косметика підходить не всім
Клієнт купує дорогий крем з ретинолом, а через тиждень отримує подразнення. Або наносить 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). Вартість розраховується індивідуально — залежить від обсягу даних і складності логіки. Оцінимо ваш проект за один день після заповнення брифу.
Отримайте консультацію — зв'яжіться з нами, щоб обговорити пілот на ваших даних. Гарантуємо прозорий розрахунок і фіксовані терміни. Замовте впровадження — перші результати через місяць.







