проєкти / FIG. 02
← усі системиAI-обробник дзвінків і аналітичний агент
Виробник тортів, ~200 звернень на день. Дзвінки транскрибуються з приховуванням персональних даних (PII), класифікуються LLM у структуровану таблицю даних — а чат-агент у Telegram і на вебсайті відповідає на «скільки негативних дзвінків цього тижня?» за секунди.
- дзвінок → класифіковано за ~30 с (було ~7 год)
- 100% охоплення дзвінків (було 30–40%)
- самовідновлення: sweeper + сповіщення про помилки
Сценарій
Сценарій виробника тортів: онлайн-пекарня приймає замовлення телефоном і організовує доставку, близько 200 дзвінків клієнтів на день — відгуки, скарги, питання щодо замовлень. До автоматизації один співробітник вручну прослуховував кожен дзвінок, оцінював тональність, проставляв категорію і вносив запис у звіт. При 200 дзвінках на день це забирало 8–10 робочих годин, тож реально опрацьовувалося лише 30–40% дзвінків — решта за замовчуванням пропускалася.
| Біль | Наслідок |
|---|---|
| 8–10 годин на день ручного прослуховування | Скарги отримують відповідь наступного дня, а то й пізніше |
| Немає зведеної статистики | Немає видимості частки негативних дзвінків, трендів за категоріями |
| Немає швидкого пошуку | Неможливо за 30 секунд відповісти на «що пішло не так минулого тижня» |
| Суб’єктивна оцінка | Різні перевіряючі — різні висновки щодо тональності |
| Охоплення 30–40% | Більшість відгуків так ніхто й не бачить |
Що я побудував
Шість workflow в n8n, що використовують спільну чергу в Google Sheets і одну n8n Data Table.
Calls: Processor (запуск за розкладом кожні 2 хвилини, 17 нод) бере URL дзвінка з черги, встановлює атомарне блокування, відправляє його в AssemblyAI на транскрипцію українською з діаризацією мовців і приховуванням PII, класифікує через LLM за тональністю й категорією та записує результат у Data Table. Дзвінки коротші за 10 секунд відсіюються ще до того, як дістануться LLM.
Calls: Stats Tool і Calls: Drill Down Tool — це підворкфлоу, які агент викликає як інструменти: перший повертає агреговані дані (загальні цифри, % негативу, топ-категорії), другий — конкретні дзвінки, відфільтровані за діапазоном дат, тональністю, категорією і лімітом. Drill-down інструмент виділено в окремий підворкфлоу саме тому, що вбудований у n8n Data Table інструмент для AI-агентів під час тестування плутав назви операторів фільтрації (_le проти _lte) — його замінив написаний вручну фільтр у Code-ноді.
Calls: Agent — це чат-інтерфейс: Telegram-бот і вебчат з basic-auth, обидва працюють на одному LangChain-агенті з пам’яттю по кожному каналу окремо, тож менеджер може запитати «скільки негативних дзвінків цього тижня?» або «покажи 3 скарги на якість» і отримати відповідь із реальними прикладами, а не шаблонне резюме.
Calls: Errors і Calls: Sweeper тримають пайплайн чесним. Errors надсилає сповіщення в Telegram із посиланням на виконання при будь-якому збої. Sweeper запускається щогодини, знаходить рядки, застряглі в статусі «Processing» довше 15 хвилин — коли колбек від AssemblyAI так і не прийшов, — і скидає їх, тож система відновлюється сама, без втручання людини.
Архітектура
Діаграма вище відповідає робочим workflow: черга в Google Sheets живить Processor, який передає транскрипцію в AssemblyAI, а класифікацію — в Gemini, записує результат у Data Table і дозволяє Agent читати цю таблицю через два спеціалізовані інструменти, поки Sweeper і Errors стежать за всім пайплайном на предмет зависань і збоїв.
Уроки, які сформували систему
- Асинхронність краща за опитування (polling). AssemblyAI транскрибує через webhook-колбек, і workflow використовує патерн n8n Wait/Resume замість опитування статусу: виконання серіалізується в базу даних і «прокидається» на колбек, тож один воркер може одночасно тримати сотні «сплячих» дзвінків, не витрачаючи ресурси.
- Блокування в Sheets має бути атомарним, інакше два запуски обробляють один дзвінок двічі.
appendOrUpdateіз зіставленням по колонках виявився достатнім примітивом, щоб зробити чергу безпечною до паралельних запусків без окремої таблиці блокувань. - Два спеціалізовані інструменти кращі за один універсальний. Розділення Stats (агрегати) і Drill Down (конкретні рядки) дало агенту чітке дерево рішень. Одному інструменту «на все» моделі було складніше коректно скористатися.
- Заміна моделі дала більше, ніж тюнінг промпту. Перехід класифікації з безкоштовної універсальної моделі на Gemini 2.5 Flash підняв частку валідного JSON на виході з ~85% до ~99% — найбільший приріст надійності в усій системі.
- Зберігай вказівник, а не сам вміст. Data Table зберігає
transcript_id, а не повний текст транскрипту — таке ощадливе до сховища рішення розтягує ліміт n8n Data Table у 50 МБ приблизно на рік даних за такого обсягу дзвінків.
Результати
Метрики виміряні в тестових прогонах — це демо-білд, а не відгук клієнта.
| Метрика | До | Після |
|---|---|---|
| Час ручного перегляду | 8–10 год/день | 0 |
| Час від дзвінка до класифікації | ~7 годин | 30–60 секунд |
| Охоплення дзвінків | 30–40% | 100% |
| Час відповіді на аналітичне питання | 15–30 хв вручну | 3–5 секунд через чат-агента |
| Час повного циклу виконання | — | ~26 секунд (виміряно) |
| Вартість роботи пайплайна | — | ~$8–12/місяць (AssemblyAI + OpenRouter) |
контакти
Маєте процес, який з'їдає години вашої команди?
Опишіть його в кількох реченнях — я відповім планом автоматизації: що збудувати, чого це торкнеться і скільки це заощадить.