AI-система оптимізації меню ресторану
Проблема: ресторани втрачають до 15% виручки через неоптимальне меню. Наша AI-система оптимізації меню ресторану (прогноз попиту страв + аналіз маржинальності) автоматизує меню-інжиніринг. Наприклад, мережа італійських ресторанів із 7 точок виявила, що 40% позицій приносили лише 10% виручки, а food waste сягав 12% закупівель. Традиційний меню-інжиніринг (матриця BCG) не враховує сезонність, час приготування та вплив на кухню. Ми створили AI-систему, яка аналізує продажі, маржинальність, відгуки гостей та прогнозує попит з точністю до 85% — це в 5 разів краще, ніж експертні оцінки (60%). Система класифікує страви за матрицею Stars/Puzzles/Plowhorses/Dogs, пропонує зміни та генерує звіт природною мовою через LLM. У результаті — приріст валової маржі на 3-6 п.п. та зниження food waste на 15-25%. Економія на закупівлях для мережі з 10 точок може сягати $6,000 на місяць. AI-система аналізує меню в 50 разів швидше, ніж людина, і в 5 разів точніше прогнозує попит. Витрати на аналіз знижуються у 50 разів порівняно з ручним.
Чому традиційний меню-інжиніринг не працює?
Більшість ресторанів покладаються на інтуїцію шеф-кухаря або ручний аналіз в Excel. Це повільно, суб’єктивно та не масштабується. Мережа з 10 точок потребує аналізу тисяч транзакцій — людині тиждень, AI справляється за годину. Крім того, ручний аналіз не враховує впливу погоди, свят та промоакцій на попит. AI-система, навчена на історичних даних, передбачає попит з точністю до 85% (проти 60% у експертних оцінок).
Як AI-система перевершує ручний аналіз у 5 разів?
Порівняйте: традиційний підхід — менеджер витрачає 3-5 днів на аналіз Excel, результати суб’єктивні та застарівають через місяць. Наша AI-система обробляє ті ж дані за 2 години, а прогноз попиту оновлюється щодня. Вона враховує 15+ факторів: день тижня, погоду, свята, промоакції та навіть відгуки гостей. Завдяки цьому точність прогнозу досягає 85-90% — в 5 разів менше помилок, ніж при ручних розрахунках. Для управління запасами це означає зниження надлишків на 15-25% та покращення оборотності.
Вирішувані проблеми
- Високий food waste — прогноз попиту дозволяє закуповувати рівно стільки продуктів, скільки потрібно, без надлишку.
- Низька маржинальність — система виявляє страви з низькою маржею (Plowhorses) та пропонує оптимізувати рецептуру або ціну.
- Перевантажене меню — класифікація Dog показує, які позиції варто прибрати, не знижуючи виручку (зазвичай видалення 10% «собак» зменшує виручку менш ніж на 2%).
- Неефективне позиціонування — Puzzle-страви з високою маржею, але низькою популярністю отримують рекомендації щодо ребрендингу, переміщення в меню або зміни опису.
Як ми будуємо систему: стек та підхід
Ми використовуємо комбінацію класичного меню-інжинірингу (матриця BCG) та ML-моделей. Система реалізує автоматизацію меню-інжинірингу за допомогою ML та LLM. Розробка ML системи для ресторану включає три компоненти: аналізатор матриці (Python, Pandas), прогноз попиту на основі градієнтного бустингу (Scikit-learn) та LLM-консультант (Claude 3.5 Sonnet, Anthropic API).
- Аналізатор матриці (Python, Pandas) — класифікує страви за 4 категоріями.
- Прогноз попиту (Gradient Boosting, Scikit-learn) — передбачає щоденні замовлення для кожної страви на тиждень вперед, враховуючи день тижня, сезон, погоду.
- LLM-консультант (Claude 3.5 Sonnet, Anthropic API) — генерує текстовий звіт з конкретними рекомендаціями українською мовою.
Приклад інтеграції з POS-системою
Система підключається до API iiko або R-Keeper та завантажує дані про транзакції в реальному часі. Для малих ресторанів достатньо щотижневого вивантаження CSV.Приклад реалізації коду — нижче. Ми використовуємо Anthropic для генерації звіту, GradientBoostingRegressor для прогнозу. Система контейнеризується в Docker, розгортається на хмарній інфраструктурі (AWS/GCP) або on-premise. Докладніше про матрицю BCG можна прочитати на Wikipedia.
import pandas as pd import numpy as np from sklearn.ensemble import GradientBoostingRegressor from anthropic import Anthropic import json class MenuEngineeringAnalyzer: """Класична матриця меню-інжинірингу + ML розширення""" def classify_menu_items(self, sales_data: pd.DataFrame) -> pd.DataFrame: """ Матриця Boston Consulting Group для меню: - Stars: висока маржа + висока популярність → зберігаємо, просуваємо - Puzzles: висока маржа + низька популярність → перейменувати/перемістити - Plowhorses: низька маржа + висока популярність → знизити собівартість - Dogs: низька маржа + низька популярність → прибираємо """ df = sales_data.copy() # Нормалізовані метрики median_popularity = df['orders_count'].median() median_margin = df['contribution_margin_pct'].median() df['high_popularity'] = df['orders_count'] > median_popularity df['high_margin'] = df['contribution_margin_pct'] > median_margin def classify(row): if row['high_popularity'] and row['high_margin']: return 'star' elif not row['high_popularity'] and row['high_margin']: return 'puzzle' elif row['high_popularity'] and not row['high_margin']: return 'plowhorse' else: return 'dog' df['category'] = df.apply(classify, axis=1) # Додаткові метрики df['revenue_share'] = df['total_revenue'] / df['total_revenue'].sum() df['margin_per_minute'] = ( df['contribution_margin_usd'] / df['avg_prep_time_minutes'].clip(1) ) return df.sort_values(['category', 'contribution_margin_usd'], ascending=[True, False]) def compute_menu_mix_impact(self, items: pd.DataFrame) -> dict: """Що станеться з виручкою при зміні меню""" stars = items[items['category'] == 'star'] dogs = items[items['category'] == 'dog'] puzzles = items[items['category'] == 'puzzle'] return { 'stars_revenue_share': stars['revenue_share'].sum(), 'dogs_revenue_share': dogs['revenue_share'].sum(), 'dogs_count': len(dogs), 'estimated_revenue_lift_from_dog_removal': ( dogs['revenue_share'].sum() * 0.6 # 60% замовлень перейде на зірки ), 'puzzles_reposition_opportunity': len(puzzles) } class DemandForecastForMenu: """Прогноз попиту на страви для закупівель""" def __init__(self): self.models = {} def train_item_model(self, item_id: str, sales_history: pd.DataFrame): """Модель прогнозу для конкретної страви""" if len(sales_history) < 60: return features = self._build_features(sales_history) y = sales_history['orders_count'] self.models[item_id] = GradientBoostingRegressor( n_estimators=100, learning_rate=0.1, random_state=42 ) self.models[item_id].fit(features, y) def _build_features(self, df: pd.DataFrame) -> pd.DataFrame: return pd.DataFrame({ 'weekday': df['date'].dt.weekday, 'month': df['date'].dt.month, 'is_weekend': (df['date'].dt.weekday >= 5).astype(int), 'is_holiday': df.get('is_holiday', 0), 'temperature': df.get('temperature_c', 15), 'is_raining': df.get('is_raining', 0), 'lag_7d': df['orders_count'].shift(7).fillna(0), 'lag_14d': df['orders_count'].shift(14).fillna(0), 'rolling_mean_7d': df['orders_count'].rolling(7).mean().fillna(0), 'special_event': df.get('special_event', 0), }).fillna(0) def forecast_week(self, item_id: str, next_7_days: pd.DataFrame) -> dict: """Прогноз замовлень на тиждень для управління запасами""" if item_id not in self.models: return {'error': 'No model trained'} features = self._build_features(next_7_days) daily_forecast = self.models[item_id].predict(features).clip(0) return { 'item_id': item_id, 'daily_forecast': daily_forecast.round().astype(int).tolist(), 'total_week': int(daily_forecast.sum()), 'peak_day': next_7_days['date'].iloc[daily_forecast.argmax()].strftime('%A'), 'confidence': 'high' if item_id in self.models else 'low' } class MenuAIAdvisor: """LLM-консультант з оптимізації меню""" def __init__(self): self.llm = Anthropic() def generate_optimization_report(self, menu_analysis: pd.DataFrame, restaurant_concept: str, season: str) -> str: """Звіт з рекомендаціями щодо меню""" stars = menu_analysis[menu_analysis['category'] == 'star'][['item_name', 'revenue_share']].head(5) dogs = menu_analysis[menu_analysis['category'] == 'dog'][['item_name', 'contribution_margin_pct']].head(5) puzzles = menu_analysis[menu_analysis['category'] == 'puzzle'][['item_name', 'contribution_margin_pct']].head(3) response = self.llm.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=500, messages=[{ "role": "user", "content": f"""You're a restaurant consultant. Provide menu optimization recommendations. Restaurant concept: {restaurant_concept} Season: {season} Stars (keep & promote): {stars.to_dict('records')} Dogs (consider removing): {dogs.to_dict('records')} Puzzles (reposition/rename): {puzzles.to_dict('records')} Provide specific recommendations in Ukrainian: 1. Which dogs to remove and why 2. How to reposition puzzle items (name changes, placement, description) 3. How to leverage stars better 4. 2-3 seasonal items to consider adding 5. Pricing adjustments for plowhorses Be specific. 3-4 paragraphs.""" }] ) return response.content[0].text def suggest_new_items(self, current_menu: list[str], trending_ingredients: list[str], cuisine_type: str) -> list[dict]: """Пропозиції нових страв на основі трендів""" response = self.llm.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=400, messages=[{ "role": "user", "content": f"""Suggest 3 new menu items for this restaurant. Cuisine: {cuisine_type} Current menu (sample): {current_menu[:10]} Trending ingredients: {trending_ingredients[:8]} For each item return JSON: {{"name": "...", "description": "...", "main_ingredients": [...], "estimated_food_cost_pct": 25-35, "positioning": "starter|main|dessert"}} Return JSON array. Suggest items that complement the current menu.""" }] ) try: return json.loads(response.content[0].text) except Exception: return [] Що входить в роботу?
| Модуль | Результат |
|---|---|
| Аналіз поточного меню | Матриця Stars/Puzzles/Plowhorses/Dogs, звіт з рекомендаціями |
| Прогноз попиту | Щотижневий прогноз для кожної страви, інтеграція з ERP |
| LLM-звіт | Текстовий документ з рекомендаціями українською, готовий до друку |
| Дашборд | Веб-інтерфейс (Streamlit/Tableau) з фільтрами за датою, категорією |
| Навчання персоналу | 2-годинна сесія для менеджерів, інструкція з оновлення даних |
| Гарантія | 3 місяці підтримки після впровадження, виправлення помилок |
Результати та метрики
| Метрика | До впровадження | Після впровадження |
|---|---|---|
| Contribution margin | базове значення | +3-6 п.п. |
| Food waste | 8-12% від закупівель | зниження на 15-25% |
| Час аналізу меню | 3-5 днів | 2 години |
| Точність прогнозу попиту | 60-70% | 85-90% |
Терміни та вартість
Система розробляється під ключ за 2-4 тижні залежно від кількості точок та доступності даних. Вартість розраховується індивідуально після аудиту. Ми гарантуємо досягнення заявлених метрик (приріст маржі, зниження waste) протягом 3 місяців після запуску.
Більше 7 років досвіду в ML-рішеннях для HoReCa, 30+ успішних проєктів. Використовуємо open-source стек (Python, Scikit-learn, Anthropic), що виключає вендор-лок.
Зв'яжіться з нами для безкоштовного демо-аналізу вашого меню. Замовте пілотний проєкт, щоб обговорити впровадження.







