KB-редактор у Leadmlyn: що в ньому є і чому ми зробили саме так
Product deep-dive по KB-редактору Leadmlyn: що в ньому є, які архітектурні рішення прийнято і що планується. Чесно про поточні обмеження.
Продукт
KB-редактор у Leadmlyn: що в ньому є і чому ми зробили саме так
Власник запускає бота, додає кілька записів у базу знань, тестує. Бот відповідає якось не так. Власник думає: «Я ж написав там усе». Але він не знає, що саме бот «побачив» з його записів — і чи побачив взагалі.
Ця проблема і стала причиною того, що ми побудували власний KB-редактор, а не сказали «використовуй Google Docs і закидай посилання».
Навіщо нам власний KB-редактор — а не просто Google Docs
Технічно можна зробити систему, яка «ковтає» посилання на Docs, Notion або PDF і індексує вміст. Багато AI-SaaS так і роблять. Проблема в тому, що власник відразу відривається від процесу: він пише в одному місці, а бот читає щось, про що власник має лише теоретичне уявлення.
У нас інший принцип: те, що бачиш у редакторі — це і є те, що потрапить у RAG. Записи видно як фрагменти, статус кожного показано явно, і одразу після редагування можна перевірити результат у playground. Ніяких прихованих перетворень між «написав» і «бот відповів».
Другий аргумент — структура. У Docs немає поняття «запис про ціну» vs «запис FAQ» vs «запис про правила скасування». В нашій системі це розрізняється через поле source_type: faq, price, file, url. Ця структура впливає на ранжування при пошуку — прайсовий запис матиме перевагу при ціновому питанні.
Що є в KB-редакторі зараз
Редактор організований навколо типів записів.
FAQ-записи (faq): пара «питання — відповідь». Це найпоширеніший тип. «Чи можна з дітьми?» / «Так, але для дітей до 7 років обов'язкова присутність батьків.» Одне питання — один запис. Не варто пакувати 5 питань в один запис — RAG шукатиме по сенсу, і один великий запис гірше знаходиться, ніж кілька маленьких.
Цінові записи (price): поле price_item_name і price_item_value. «Лазертаг будній день» / «180 грн/особа». Структурований формат з окремими полями дозволяє рендерити ціни у фіксованому вигляді, що допомагає RAG при точних числових запитах.
Файли (file): PDF, docx — завантажуються напряму, розбиваються на чанки автоматично. Зручно для умов договору або детального прайс-листа. Для поточної версії є нюанс: файли без явної структури (суцільний текст) індексуються гірше, ніж ручні записи.
URL (url): індексація зовнішньої сторінки. Наприклад, сторінки з цінами на сайті. Система завантажує і парсить контент при додаванні, але не оновлює автоматично при зміні сторінки — для актуальних даних краще ручний запис.
Кожен запис має статус: pending (щойно доданий, очікує індексації), processing (векторизується), (готовий, бот може використовувати), (щось пішло не так, є повідомлення про помилку). Статус означає, що запис проіндексовано і потрапить у RAG.
Відомі обмеження і що планується
Чесно про те, чого зараз немає.
Немає повнотекстового пошуку по KB в UI. Якщо в тебе 150 записів і ти хочеш знайти всі, де згадується «лазертаг» — доведеться гортати. Пошук по KB-записах в адмін-панелі — у планах, але поки не реалізовано.
Немає bulk import з таблиці. Завантажити прайс як CSV і автоматично перетворити на price-записи — очевидна потреба. Є csv_schema_inferrer у сервісному шарі, але UI для цього ще не готовий.
Немає автоматичного оновлення URL. Якщо ти додав сторінку сайту, зміни на ній не підтягнуться автоматично. Треба вручну оновити або перезавантажити URL.
Файли без явної структури індексуються гірше. PDF, в якому текст суцільним потоком без заголовків — розбивається на довільні чанки. Якщо в тебе є такий документ, краще перенести ключові факти в ручні FAQ-записи.
Все перераховане — реальні обмеження поточної версії, а не маркетингові «ми над цим працюємо». Ці речі є в roadmap.
Як максимально використати KB-редактор
Кілька практичних правил, які виходять із розуміння того, як RAG читає записи.
Один факт — один запис. Не «Ціни і умови бронювання в одному» — а окремо «Ціни на лазертаг» і окремо «Умови бронювання». Маленький сфокусований запис знаходиться краще.
Запитання у FAQ-записах пишіть так, як пише клієнт. Не «Чи відповідає заклад за збереження особистих речей клієнтів?» — а «Де залишити речі? Є камера схову?». Вектор FAQ-запитання формується разом з відповіддю і впливає на матчинг.
Після кожної зміни — тест у playground. Змінив запис → зайшов у playground → задав питання, яке має спирається на цей запис → перевірив, що бот відповів правильно і показав потрібний чанк. Без цього кроку не знаєш, чи зміна спрацювала.
Деактивуй замість видалення. Принцип, про який вже писав — але він варто повторення. Видалення незворотне. Деактивація — ні. Для сезонних записів заведи звичку: не видаляти, а перемикати is_active.
Слідкуй за довжиною. Якщо запис перевищує 300–400 слів — це сигнал, що там кілька тем, і їх варто розбити. Системне обмеження для KnowledgeFact — 500 символів, це хороший орієнтир для коротких фактичних записів.
Засновник Leadmlyn. Будую AI-менеджерів для leisure-бізнесу в Україні.