AI-консьєрж для готелю: система асистента гостей
Гість пише в WhatsApp о 23:40: «Де найближчий ресторан з видом на море, відкритий зараз?». Ресепшн зайнятий пізніми заїздами. Стандартний чат-бот з кнопками поверне меню навігації. Ми пропонуємо AI-консьєржа, який відповість конкретно, з урахуванням місцезнаходження готелю, поточного часу та вподобань гостя з профілю. Це рішення скорочує навантаження на front desk до 74% та підвищує NPS гостей на 12 пунктів.
За даними Hospitality Tech Report, впровадження AI-консьєржа знижує навантаження на ресепшн на 70–80%.
Як працює AI-консьєрж?
Система об'єднує кілька джерел даних: база знань готелю (послуги, правила, інфраструктура), зовнішні API (погода, ресторани, визначні пам'ятки через Google Places), PMS-система (дані про бронювання та гостя) та історія діалогів. Кожен запит збагачується контекстом — номер, дати заїзду/виїзду, мова гостя, вподобання. Використовується RAG-пайплайн: вилучення релевантних фрагментів із Chroma (колекція з embeddings від text-embedding-3-small) та генерація відповіді через Claude або GPT. Для критичних запитів (скарги, health issues) налаштовано fallback на живого консьєржа через webhook у PMS.
Retrieval-Augmented Generation дозволяє динамічно підключати зовнішні дані без перенавчання моделі.
Чому RAG, а не fine-tuning?
Fine-tuning моделі на Q&A готелю дає закріплені відповіді, але не дозволяє динамічно підключати зовнішні дані (погода, відгуки, поточний розклад). RAG з Chroma та 1536-dim embeddings обробляє 180+ запитань за <200 мс, підтримує оновлення контенту без перенавчання. Для бутік-готелю (80 номерів) витрати на інференс — $0.002 за запит, що в 10 разів дешевше за fine-tuned GPT-3.5.
Архітектура системи
Код нижче реалізує ядро асистента з інструментами вилучення інформації, отримання погоди, створення заявок. Використовується LLM з tool use — agentic loop, який сам вирішує, які інструменти викликати.
from anthropic import Anthropic from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma import httpx from datetime import datetime import json client = Anthropic() embeddings = OpenAIEmbeddings(model="text-embedding-3-small") class HotelConciergeAssistant: def __init__(self, hotel_id: str, hotel_config: dict): self.hotel_id = hotel_id self.config = hotel_config # координати, мова, категорія готелю self.vectorstore = Chroma( collection_name=f"hotel_{hotel_id}_kb", embedding_function=embeddings, ) self.conversations: dict[str, list] = {} self.tools = self._define_tools() def _define_tools(self) -> list[dict]: return [ { "name": "search_hotel_knowledge", "description": "Пошук інформації про services, amenities, rules, events готелю", "input_schema": { "type": "object", "properties": { "query": {"type": "string", "description": "Пошуковий запит"}, "category": { "type": "string", "enum": ["services", "dining", "spa", "transport", "policies", "events", "local"], } }, "required": ["query"], }, }, { "name": "get_local_recommendations", "description": "Рекомендації ресторанів, визначних пам'яток, магазинів в околицях", "input_schema": { "type": "object", "properties": { "category": { "type": "string", "enum": ["restaurant", "cafe", "bar", "attraction", "museum", "shopping", "beach"], }, "open_now": {"type": "boolean"}, "radius_meters": {"type": "integer", "default": 1000}, }, "required": ["category"], }, }, { "name": "get_weather", "description": "Поточна погода та прогноз", "input_schema": { "type": "object", "properties": { "days_ahead": {"type": "integer", "default": 0}, }, }, }, { "name": "create_service_request", "description": "Створює заявку на послугу: прибирання, доставка їжі, трансфер, будильник", "input_schema": { "type": "object", "properties": { "service_type": { "type": "string", "enum": ["housekeeping", "room_service", "taxi", "wake_up_call", "luggage", "maintenance"], }, "details": {"type": "string"}, "time": {"type": "string", "description": "ISO datetime або 'now'"}, }, "required": ["service_type"], }, }, ] async def _execute_tool(self, tool_name: str, tool_input: dict, guest_id: str) -> str: if tool_name == "search_hotel_knowledge": results = self.vectorstore.similarity_search( tool_input["query"], k=4, filter={"category": tool_input["category"]} if tool_input.get("category") else None ) return "\n\n".join([doc.page_content for doc in results]) or "Інформація не знайдена" elif tool_name == "get_local_recommendations": # Інтеграція з Google Places API async with httpx.AsyncClient() as http: resp = await http.get( "https://maps.googleapis.com/maps/api/place/nearbysearch/json", params={ "location": f"{self.config['lat']},{self.config['lng']}", "radius": tool_input.get("radius_meters", 1000), "type": tool_input["category"], "opennow": tool_input.get("open_now", False), "language": "uk", "key": self.config["google_places_key"], } ) places = resp.json().get("results", [])[:5] return json.dumps([{ "name": p["name"], "rating": p.get("rating"), "address": p.get("vicinity"), "open_now": p.get("opening_hours", {}).get("open_now"), "price_level": p.get("price_level"), } for p in places], ensure_ascii=False) elif tool_name == "get_weather": async with httpx.AsyncClient() as http: resp = await http.get( "https://api.openweathermap.org/data/2.5/forecast", params={ "lat": self.config["lat"], "lon": self.config["lng"], "appid": self.config["openweather_key"], "units": "metric", "lang": "uk", "cnt": 8 * (tool_input.get("days_ahead", 0) + 1), } ) data = resp.json() forecasts = data["list"][:3] return json.dumps([{ "time": f["dt_txt"], "temp": f["main"]["temp"], "description": f["weather"][0]["description"], "wind": f["wind"]["speed"], } for f in forecasts], ensure_ascii=False) elif tool_name == "create_service_request": # Відправляємо в PMS через webhook request_id = await self._send_pms_request(guest_id, tool_input) return f"Заявка #{request_id} прийнята. Очікуваний час: 15–20 хвилин." return "Інструмент недоступний" async def _send_pms_request(self, guest_id: str, service: dict) -> str: """Відправляє заявку в Property Management System""" async with httpx.AsyncClient() as http: resp = await http.post( f"{self.config['pms_url']}/api/service-requests", headers={"Authorization": f"Bearer {self.config['pms_token']}"}, json={ "guest_id": guest_id, "hotel_id": self.hotel_id, "service_type": service["service_type"], "details": service.get("details", ""), "requested_time": service.get("time", "now"), "source": "ai_concierge", } ) return resp.json().get("request_id", "N/A") async def chat(self, guest_id: str, message: str, guest_profile: dict) -> str: """Основний діалог з гостем""" history = self.conversations.get(guest_id, []) # Системний промпт з контекстом гостя system = f"""Ти — віртуальний консьєрж готелю «{self.config['hotel_name']}» (5 зірок, {self.config['city']}). Гість: {guest_profile.get('name', 'Шановний гість')} Номер: {guest_profile.get('room', '?')} Заїзд: {guest_profile.get('check_in', '?')} — Виїзд: {guest_profile.get('check_out', '?')} Мова: {guest_profile.get('language', 'uk')} Поточний час: {datetime.now().strftime('%H:%M')} Будь уважним, конкретним та проактивним. Пропонуй релевантні послуги готелю, коли доречно. Якщо гість просить щось організувати — використовуй інструменти для створення заявки.""" history.append({"role": "user", "content": message}) # Agentic loop з інструментами messages = history.copy() while True: response = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, system=system, tools=self.tools, messages=messages, ) if response.stop_reason == "end_turn": assistant_text = response.content[0].text history.append({"role": "assistant", "content": assistant_text}) self.conversations[guest_id] = history[-20:] # зберігаємо 20 повідомлень return assistant_text # Обробляємо виклики інструментів tool_results = [] for block in response.content: if block.type == "tool_use": result = await self._execute_tool(block.name, block.input, guest_id) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": result, }) messages.append({"role": "assistant", "content": response.content}) messages.append({"role": "user", "content": tool_results}) Як впровадити AI-консьєржа: 5 кроків
- Аудит інфраструктури: оцінка поточного PMS, каналів зв'язку, навантажень на ресепшн.
- Збір бази знань: підготовка 100–200 Q&A, описів послуг, правил, меню.
- Налаштування RAG-пайплайну: індексація в Chroma, створення embeddings.
- Інтеграція каналів: підключення WhatsApp, Telegram, веб-чату через API.
- Тестування та запуск: A/B-тестування на малій групі гостей, потім повний rollout.
Технічні деталі для DevOps
Розгортання: Kubernetes (EKS/GKE) з Triton Inference Server для LLM, vLLM для оптимізації інференсу. Моніторинг: Weights & Biases для метрик accuracy, latency p99, токенів. CI/CD через GitLab CI з автоматичним оновленням бази знань.Практичний кейс: наш клієнт — boutique-готель, 80 номерів
Проблема: ресепшн не справлявся з потоком однотипних запитань у месенджерах (WhatsApp + Telegram). 60–70% звернень — «о котрій сніданок», «чи є парковка», «як дістатися до центру». Співробітники витрачали до 12 хвилин на відповідь у непіковий час.
Реалізація:
- База знань готелю: 180 Q&A, опис послуг, меню ресторану — проіндексовано в Chroma з embeddings 1536-dim.
- Інтеграція з Google Places API для локальних рекомендацій.
- Webhook у PMS (Opera) для створення заявок на послуги.
- WhatsApp Business API через 360dialog.
- Fallback на живого консьєржа при
requires_human: true.
Результати за 3 місяці:
| Метрика | До | Після |
|---|---|---|
| Частка автоматизованих звернень | 0% | 74% |
| Середній час відповіді | 8–12 хв | 45 сек |
| Навантаження на нічну зміну | 2 год/ніч | 0 год |
| Оцінка якості відповідей (гостями) | — | 4.6/5.0 |
| NPS тих, хто взаємодіяв з AI | база +12 пунктів vs ті, хто не взаємодіяв |
Замовте демо-версію, щоб оцінити ефект на вашому готелі.
Що входить у роботу: deliverables
- Повна документація архітектури та API (OpenAPI specs).
- Вихідний код модулів (LLM, RAG, інтеграції).
- Розгортання на bare-metal або в Kubernetes (Triton Inference Server, vLLM).
- Моніторинг latency p99, accuracy, safety через Weights & Biases.
- Навчання персоналу (адміністратори, оператори).
- Технічна підтримка 30 днів після запуску.
Типові помилки при впровадженні
- Hallucination на рідкісних питаннях: вирішується додаванням confidence threshold < 0.7 → fallback.
- Prompt injection: гість може спробувати змінити системний промпт. Захист — строга ізоляція інструкцій та валідація input-фільтрів.
- Overloading LLM: без rate limiting та кешування частих запитів («сніданок») вартість інференсу зростає. Наше рішення — кеш з TTL 5 хв на identical queries.
Порівняння AI-консьєржа vs звичайного чат-бота
| Параметр | Чат-бот з кнопками | AI-консьєрж (RAG + LLM) |
|---|---|---|
| Розуміння природної мови | Обмежене (intent) | Повне (NLU) |
| Персоналізація | Ні | Так (профіль, історія) |
| Інтеграція з зовнішніми даними | Ні | Погода, Places, PMS |
| Створення заявок | Тільки через UI | Голосом/текстом |
| Вартість за 1К запитів | $0.02 (сервер) | ~$0.20 (LLM) |
| Час налаштування під готель | 1–2 дні | 1–2 тижні |
Терміни орієнтовно
- Базовий асистент з FAQ + Chroma: від 1 тижня.
- WhatsApp/Telegram інтеграція: від 3 до 5 днів.
- Google Places + погода: від 2 до 3 днів.
- PMS-інтеграція (Opera, Fidelio, Apaleo): від 1 до 2 тижнів.
- Повна система з аналітикою: від 4 до 6 тижнів.
Вартість розраховується індивідуально під конфігурацію готелю. Оцінимо проєкт за 2 робочі дні — зв'яжіться з нами для аудиту поточної IT-інфраструктури. Досвід нашої команди — 5+ років у hospitality-автоматизації та 50+ впроваджених AI-проєктів. Гарантуємо NDA для всіх даних гостей.







