Контекст: роки досвіду + Excel = bottleneck
Власник дистриб'юторської компанії автозапчастин (десятки марок, ~3,000 SKU позицій, ~15,000 одиниць на складі) вийшов на нас із простою болючкою:
"Менеджери відповідають на 70+ повторних запитів на день. Більшість починається з 'у вас є запчастина для мого Ford Focus 2014?'. На це йде 5-10 хвилин на запит. Я хочу щоб бот відповідав сам, а менеджер вже потім — на складні."
Архітектурно це B2B self-service catalog з трьома складними викликами:
- Клієнти присилають VIN-номери — треба декодувати марку/модель/рік
- У менеджерів база збережена за рукописними категоріями (амортизатор, сайлентблок, шрус) — треба зрозуміти що клієнт хоче, навіть якщо він пише "хочу те що там колеса тримає"
- Не можна замовкати на "немає в наявності" — треба пропонувати альтернативи або записувати у заявку
Що ми побудували (перша версія за ~3 тижні)
Структура:
- 5,378 SKU нормалізовані з 1С + 4 Excel-каталогів
- 69 брендів, 30,365 одиниць stock
- 1,211 категорій + 809 позицій + 42 моделі підтягнуті regex-екстрактором з рукописних назв
- 60 "коренів запчастин" з нотаток власника (наприклад: "амортизатор передній" — це 18,125 SKU, "відбійник" — 5,570)
Smart query layer:
-
VIN decode через NHTSA vPIC API. Європейські моделі (моделі з американськими OEM-номерами) — додатковий fallback через Apify scraping. VIN auto-correction для частих помилок (O→0, I→1).
-
Root search. Замість "знайди всі 18,125 амортизаторів" → бот показує групи по моделях, ставить уточнюючі питання, доводить до 5-10 кандидатів.
-
Conversational funnel. Клієнт пише вільним текстом → бот задає питання за категоріями (марка → модель → рік → конкретна вузол) → доходить до конкретного SKU.
-
Cross-references. Одна деталь = 3 OEM-номери (наприклад ASH ↔ K2GZ ↔ EU). Бот шукає по всіх трьох.
-
OEM regex. Підтримка кількох форматів OEM-номерів, включно зі старими.
No-stock handling:
- Бот ніколи не каже просто "немає"
- Пропонує альтернативи з cross-reference
- Якщо все одно немає — записує заявку власнику з усім контекстом
Auto-forward логіка:
- VIN no-match → автоматичне повідомлення власнику з повним контекстом (VIN + NHTSA decode + username + chat_id)
- Sensitive query → менеджер бачить діалог у real-time
Технічний стек
- Node.js + TypeScript — основний бот, isolated PostgreSQL (порт 5433)
- Gemini 2.5 Flash — NLU + контекстуальні відповіді
- Claude Haiku 4.5 — QC layer, фінальний фільтр для VIN-search (підвищив precision з 30% до 96.7%)
- Apify — VIN decoder fallback для європейських моделей
- NHTSA vPIC API — primary VIN decode
- PostgreSQL + pgvector — каталог + embeddings для semantic search
Результати
| Метрика | До | Після |
|---|---|---|
| Bench accuracy (soft) | n/a | 96.7% |
| Bench accuracy (strict) | n/a | 30% (стартова, ще оптимізуємо) |
| Час на типовий запит | 5-10 хв (менеджер) | 30-90 секунд (бот) |
| Doc/photo handler | manual | auto (RU↔UA нормалізація) |
| 7,339 клієнтів CRM | напівспящі | готові до self-service |
Real-world перевірка: після інтеграції Excel-каталогу з 1С (4×/день sync), бот витримав 73K ₴/18 угод за день без одного збою.
3 lessons-learned
1. Реальні дані складніші за demo. Перші тести на 1,000 нормалізованих SKU йшли 99%. На 5,378 з рукописними категоріями — упало до 65%. Шлях вгору — regex-екстрактор + Claude QC layer + 60 "коренів" з менеджерських нотаток.
2. AI commit-or-escalate, не AI-fail-silent. Бот або відповідає впевнено, або одразу пише "переключаю на людину". Жодних "вибачте, не зрозумів". Клієнти B2B не мають часу на ввічливе незнання.
3. Pirated infrastructure — стратегічне НІ. Власник пропонував підключити доступ до закритих каталогів через RDP, які роздавав знайомий. Ми відмовились — DMCA-ризики, single point of failure (cease-and-desist лист = bot мертвий), repuration kill для майбутніх enterprise. Залишились на NHTSA + публічні API + структурований каталог.
Хочете подібне?
Каталог із 5,000+ SKU + Telegram self-service + dashboard для власника — типовий enterprise проект Lumina. перша версія за 2-3 тижні, повна система з інтеграціями й передачею за кілька місяців, з вашими даними.