Client Personal Demo (Open Source)
Role Solo Creator / Architect
Period Aug 2026
Stack
Go chi pgx/v5 PostgreSQL JWT Telegram Bot API Docker Compose Ollama (optional)
ragline — бекенд AI/RAG Telegram-бота підтримки preview

ragline — бекенд AI/RAG Telegram-бота підтримки

Огляд

Незалежний demo-проєкт: REST API на Go для AI-ботів підтримки — база знань, повнотекстовий пошук Postgres та явний поріг довіри, що передає питання людині замість вигадування відповіді. Моделює патерн AI-ботів підтримки: власна документація клієнта проглядається пошуком, і бот має відрізняти “я знайшов відповідь” від “я не знайшов нічого релевантного” — випадок, який наївний бот приховує правдоподібною вигадкою.

Результат: бот, що ніколи не повторює здогадку з низькою довірою навіть із власного кешу, і ніколи не віддає закешовану відповідь після редагування документа, на якому вона ґрунтувалась — доведено на 4 реальних сценаріях, не заявлено.


Справжня складна задача

Справжній режим відмови RAG-бота — не “неправильна відповідь”, а “впевнена неправильна відповідь”. Пошук завжди повертає щось, якщо не обмежений; питання в тому, чи знає бот, коли це щось недостатньо добре, щоб відповідати. Окремо: закешована для швидкості відповідь має інвалідуватись при редагуванні вихідного документа.


Архітектура

Потік рішень ragline: пошук, потім ескалація, кеш або генерація

Кожне питання проходить одну оркестрацію: повнотекстовий пошук бази знань → пошук кеш-запису, відфільтрований за поточною версією документа найкращого збігу → чиста функція Decide → ескалація, видача кешу, або генерація-й-кешування свіжої відповіді — з логуванням питання в обох випадках.


Ключові інженерні рішення

Рішення Чому
Decide(hasMatch, topScore, threshold, cacheHit) винесена як чиста функція Жодного I/O, повністю юніт-тестована — низький бал веде до ескалації навіть якщо для цього запиту є кеш-запис, тож бот не може нескінченно повторювати одну погану здогадку
Кеш відповідей з ключем (query_text_hash, document_id, document_version) Редагування підвищує version; наступне ідентичне питання не знаходить застарілий рядок кешу й регенерує проти нового вмісту, замість мовчки видавати видалену інформацію
OR-об’єднаний tsquery з конфігурацією 'english' замість AND за замовчуванням у websearch_to_tsquery Знайдено наживо, не спроєктовано заздалегідь: AND-запит провалювався на будь-якому реальному питанні зі словами, відсутніми в цільовому документі (майже всі); ранній OR-фікс над 'simple' дозволяв нерелевантним питанням обганяти релевантні через спільні стоп-слова — вбудоване прибирання стоп-слів + стемінг 'english' виправили обидва одразу
Генерація за pluggable інтерфейсом Generator TemplateGenerator (за замовчуванням, нуль I/O, екстрактивний) не потребує зовнішнього сервісу; опційний OllamaGenerator (реальний локальний LLM) підключається через OLLAMA_URL, не торкаючись рішення ескалації/кешування взагалі — той самий поділ, що й pluggable Generator у tumanomir

Результати

  • Повний REST API: JWT-авторизація, CRUD бази знань (PUT підвищує version), POST /api/ask зі спільним секретом (machine-to-machine, не дія персоналу), черга ескалацій для персоналу
  • Рішення ескалація/генерація/кеш чисте й повністю юніт-тестоване — включно з випадком “кеш є, але довіра низька — все одно ескалація” — без потреби в БД для go test ./...
  • Перевірено наскрізно через docker compose up на одному засіяному документі “Billing FAQ”:
    • Релевантне питання знайшло збіг і згенерувало відповідь (бал 0.2)
    • Те саме питання іншим регістром влучило в кеш замість регенерації
    • Нерелевантне питання (“швидкість польоту незавантаженої ластівки”) не знайшло нічого й ескалювалось — саме той випадок, для якого знадобився фікс пошуку вище; до нього це питання отримувало бал вищий, ніж справжнє питання про білінг, лише через спільні стоп-слова
    • Після редагування документа (version 1 → 2) те саме питання регенерувалось замість видачі застарілого кешу, а третє ідентичне питання коректно влучило у свіжий кеш

Код: github.com/valpere/ragline


Стек

Go · chi (router) · pgx/v5 (без ORM) · golang-jwt · bcrypt · PostgreSQL (повнотекстовий пошук: tsvector, ts_rank_cd, конфігурація english) · Docker Compose · testify · опційно: Ollama (локальний LLM, pluggable)