Чат-бот для запитань про державну політику, який посилається на джерела, а не вгадує
Як RAG-чат-бот на LangChain, pgvector і Express відповідає на запитання громадян за офіційними документами, з посиланнями на джерела й порогом упевненості.
Чат-бот, що відповідає на запитання про державну політику, легко збудувати й важко йому довіряти. Мета тут не гладкий текст. Мета — відповідь, яку громадянин може звірити з офіційним документом. Навколо цієї єдиної ідеї й побудовано проєкт policy-qa-system, RAG-чат-бот із відкритим кодом.
Публічно, але нечитабельно
Держави публікують величезні обсяги матеріалів: розміри допомоги, вимоги до заяв, правила права на виплати. Формально все це є в інтернеті. Фактично звичайній людині придатне дуже небагато. Той, хто просто хоче дізнатися, що йому належить або які документи принести, натрапляє на 30-сторінковий текст, написаний для працівників відомства.
Далі все передбачувано. Люди дзвонять на гарячу лінію й питають те, що вже опубліковано, або здаються й діють навмання. У великих державних службах, де багато документів, цей розрив трапляється постійно. Інформація існує. Бракує способу поставити їй запитання.
Система закриває цей розрив за допомогою генерації з доповненням через пошук (RAG). Люди ставлять побутові запитання простою мовою й отримують відповідь, що спирається на справжній документ-джерело, з доданим посиланням. Це не універсальний чат-бот, який імпровізує на тему політики. Він говорить тільки на основі документів, які йому дали.
Знайти, прочитати, відповісти, послатися
Кожне запитання проходить чотири кроки:
- Пошук у проіндексованих документах фрагментів, що найкраще підходять до запитання.
- Читання цих фрагментів разом із запитанням.
- Відповідь звичайною мовою, а не канцеляритом.
- Зазначення точного джерела, щоб відповідь можна було перевірити, а не просто повірити.
Більшість проєктів чат-ботів пропускають останній крок, а тут він найважливіший. Відповідь про належні виплати корисна, тільки якщо хтось може її підтвердити. Тому кожна відповідь має посилання, а якщо нічого доречного не знайшлося, система каже, що не впевнена, замість того щоб вгадувати.
Приклад простою мовою
Візьмімо запитання «Скільки становить щотижнева виплата на двох дітей?» Відповідь виглядає так:
For 2 children: first child gets the standard rate, second child
gets the additional-child rate (combined weekly and yearly totals
shown together). An income-based charge may apply above a set
household income threshold.
Source: Official rates document, section on child payments
Цифри залежать від того, документи якої країни проіндексовано, бо система не прив'язана до одного набору правил. Це шаблон для запитань і відповідей громадян, а не фіксований набір даних.
Технологічний стек
- Фронтенд: React 18, TypeScript і Tailwind CSS
- Бекенд: Node.js з Express
- ШІ та RAG: LangChain і LangGraph
- Векторне сховище: PostgreSQL з pgvector
- Розгортання: Docker
Нічого екзотичного. Команда, яка використовуватиме це всерйоз, замінить приклади документів власним офіційним набором, а пошук, посилання й генерація простою мовою лишаться як є.
Архітектура
Запит іде від запитання користувача через інтерфейс на React до Express API, який передає його в ланцюжок пошуку. Ось схема:
User question
│
▼
React UI ──► Express API
│
▼
LangChain retrieval ──► PostgreSQL + pgvector (indexed policy docs)
│
▼
LLM answer generation (grounded in retrieved sections)
│
▼
Answer + citation + confidence score
Оцінка впевненості заслуговує не меншої уваги, ніж сама відповідь. Коли пошук не знаходить нічого достатньо близького до запитання, система так і повідомляє, і модель не отримує нагоди заповнити прогалину чимось правдоподібним.
Код, який має значення
По-перше, ланцюжок не видає вільний текст сам по собі. Разом із відповіддю він мусить повернути джерело:
const response = await chain.invoke({
question,
context: retrievedChunks,
});
return {
answer: response.answer,
sources: retrievedChunks.map(c => ({
document: c.metadata.document,
section: c.metadata.section,
})),
confidence: response.confidence,
};
По-друге, поріг упевненості вирішує, відповідати чи визнати, що нічого не знайдено:
if (topMatchScore < CONFIDENCE_THRESHOLD) {
return {
answer: "I couldn't find a reliable answer to that in the indexed documents.",
sources: [],
};
}
Перевірка крихітна, але саме вона відділяє чат-бот, на який люди можуть покластися, від того, що лише звучить упевнено.
Що спрацювало
- Обов'язкові посилання від самого початку покращили пошук. Розмите збігання одразу впадає в око, коли треба показати, звідки воно взялося.
- Навіть грубий поріг упевненості різко зменшив кількість хибних відповідей, виданих упевненим тоном. Це здавалося дрібною функцією, а виявилося одним із найсильніших чинників довіри.
- Змінний набір документів означає, що та сама система може обслуговувати зовсім різні сфери політики, досить переіндексувати.
Що далося важко
- Спрощувати, не спотворюючи. Формулювання в нормативних текстах точні не просто так, і зробити їх приязнішими, не втративши умову на кшталт ліміту доходу чи правила права на виплату, потребує справжньої ретельності. Повністю це не розв'язано.
- Розуміти, коли сказати «не знаю». Занизький поріг дозволяє системі відповідати на те, на що не варто, а зависокий змушує відмовлятися від запитань, з якими вона б добре впоралася. Практичним рішенням стало ручне налаштування на невеликому наборі реальних запитань.
- Зрілість. Це основа для подальшої роботи, а не готовий до розгортання продукт. Перш ніж його побачать реальні користувачі, потрібен нормальний конвеєр завантаження документів, постійна перевірка прикладів відповідей і тестування на граничних випадках.
Місце серед інших проєктів
Він входить до невеликої родини ШІ-проєктів із відкритим кодом, побудованих на оркестрації LLM через LangChain і LangGraph: система запитань і відповідей за документами, агент для код-рев'ю та інструмент, що перетворює голосові нотатки на користувацькі історії для Agile. Спільний ухил у них один — до відповідей, які можна перевірити, а не до відповідей, що просто звучать правильно.
Спробуйте
Репозиторій швидко запускається локально:
git clone https://github.com/Srameshgitnow/policy-qa-system.git
cd policy-qa-system
npm install
npm run dev
У README описано налаштування, змінні середовища та індексацію власних документів. Прогалини в логіці посилань та ідеї щодо порогу впевненості вітаються у вигляді issues або pull request.