Як навучыць штучны інтэлект чытаць вашыя дакументы і адказваць на пытанні па іх
Вітанкі спадарства.
Працягваем наш трып у свет штучнага інтэлекту. І сёння — рэальна цікавая тэма: разбіраемся, што такое RAG (Retrieval-Augmented Generation), чаму ўсе пра яго гавораць і як зрабіць яго на ўласным камп’ютары, нават без воблачных сэрвісаў.
Так-так, без OpenAI, API-ключоў і без платных падпісак. Усё будзе працаваць лакальна — з дапамогай phi-4 ад Microsoft, gemma3 ад Google, трохі LangChain (не пужайцеся, дакранемся толькі павярхоўна) і вектарнай базы Qdrant.
Навошта нам гэты RAG?
Вялікія моўныя мадэлі (LLM) — гэта класна. Яны могуць напісаць казку, сфармуляваць адказ, нават “паразмаўляць”. Але толькі на тым, што ўжо ведаюць.
А калі табе трэба, каб AI адказваў на пытанні па тваёй уласнай дакументацыі? Ці рабіў высновы на падставе ўнутраных файлаў? У такім выпадку стандартная LLM — як бы “разумная, але нічога не ведае”.
І вось тут на арэну выходзіць RAG. Ён нібы дае мадэлі “шпаргалку” — падсоўвае патрэбныя дакументы прама перад генерацыяй адказу. Гэта як бы сказаць: “Вось, пачытай спачатку, а потым адказвай”.
RAG пад капотам (але проста)
Каб зразумець, як усё працуе, трэба тры рэчы:
- Эмбэдынгі — гэта калі тэкст пераўтвараецца ў вектар. Лічбы, што адлюстроўваюць сэнс сказанага.
- Вектарная база (Qdrant) — туды мы і “захоўваем сэнс”.
- LangChain — звязвае ўсё разам. Ён чытае тэксты, пераўтварае іх у эмбэдынгі, адпраўляе ў базу, а потым знаходзіць патрэбнае (звяртаецца да базы) і “падае” гэта мадэлі.
Крыху дэталяў
🔹Дык што такое эмбэдынгі?
Эмбэдынг — гэта лічбавае прадстаўленне тэксту. Калі сказаць больш тэхнічна, гэта вектар (спіс лічбаў), які адлюстроўвае сэнс тэксту. Два падобныя тэксты будуць мець блізкія эмбэдынгі, а розныя — далёкія.
🔹 Навошта яны?
Каб шукаць “па сэнсе”, а не па дакладных словах. Звычайны пошук тыпу ctrl + F не ведае, што “гусь” і “гусак” — гэта амаль адно і тое ж. Вектарны пошук — ведае.
🔹 Дзе мы іх захоўваем?
У вектарнай базе дадзеных. У нашым выпадку — гэта Qdrant. Яна спецыяльна распрацаваная, каб захоўваць вектары і хутка знаходзіць найбліжэйшыя па сэнсе.
🔹 А што робіць LangChain?
LangChain — гэта мост (агульна - фрэймворк) паміж мадэллю, базай і вашымі дакументамі. Ён разбівае тэксты, стварае эмбэдынгі, адпраўляе іх у Qdrant, а потым, калі вы задаеце пытанне, шукае адпаведныя фрагменты і падстаўляе іх у мадэль перад генерацыяй адказу. У нашым выпадку мы будзем выкарыстоўваць толькі некаторыя яго магчымасці.
Практыка: ствараем RAG-сістэму
А цяпер — да справы! Мы створым лакальную сістэму, якая:
- Чытае PDF-файл,
- Разбівае яго на тэкставыя кавалкі,
- Стварае эмбэдынгі праз phi-4,
- Загружае іх у Qdrant,
- Рэалізуе пошук па дакументах,
- І нарэшце — дазваляе мадэлі адказваць на вашы пытанні на падставе гэтых дакументаў.
Што выкарыстоўваем:
- phi-4 ад Microsoft (праз Ollama) для эмбэдынгу ,
- gemma3 ад Google у якасці моўнай мадэлі,
- LangChain — для ланцужкоў,
- Qdrant — як вектарную базу,
- PDF — у якасці нашай крыніцы інфармацыі.
⚠️ Калі ў цябе камп’ютар не NASA-рэйтынгу, усё яшчэ нармальна. У мяне 32 ГБ аператыўкі — і ўсё працуе. Але калі менш — бяры мадэлі лягчэйшыя. І не саромейся пісаць у каментарах, калі нешта не заводзіцца.
Калі ў вас больш слабая машына - то ёсць верагоднясць што прыйдзецца браць мадэлі паменьш. Калі што - то пішыце у каментарах.
Як гэта выглядае агулам:
- Загружаем PDF → атрымліваем тэкст
- Разбіваем тэкст на кавалкі
- Для кожнага кавалка ствараем эмбэдынг (phi-4)
- Захоўваем эмбэдынгі ў Qdrant
- На запыт карыстальніка — шукаем блізкія кавалкі тэксту
- Падаём іх у мадэль разам з пытаннем
- Атрымліваем разумны адказ
🚀 Усталеўваем ollama
Першы крок — ставім Ollama. Гэта простая праграма, праз якую запускаюцца мадэлі лакальна. Ідзем на сайтhttps://ollama.com/ — і націскаем “Download”. Усталёўка — хвілінная справа.
Пасля усталявання запампуем патрэбныя нам мадэлі - гэта будзе gemma3:12b (Можна і gemma3:27b, але толькі калі ў цябе шмат памяці — яна жадная.) і phi4. Можна ўсталяваць толькі апошнюю але з беларускай мовай у яе слабавата.
Устаноўка мадэляў ажыццяўляецца камандамі
ollama run gemma3:12b
Пасля таго як мадэль спампуецца адчыніцца поле ўводу, праз якое мы можам пакамунікаваць з устаноўлена мадэллю. Гемма сярод лакальных мадэляў мне падаецца зараз адна з самых моцных, і крыху нават піша па-беларуску. Яе мы будзем выкарыстоўваць для напісання адказаў.
** 🧠 Усталюем phi4**
ollama run phi4
Гэта мадэль будзе выкарыстоўвацца для эмбэдынгу. Phi-4 трохі лепш разумее беларускую, чым многія іншыя лакальныя мадэлі, але ўсё роўна — з беларускай мовай бывае вельмі цяжкавата. Часам вынікі будуць “так сабе, ці увогуле ніяк” — таму не чакай цудаў, але ў агульным — працуе. Тут галоўнае паказаць прынцып
⚙️ Усталеўваем BUN
Цяпер нам патрэбна рэч пад назвай Bun. Гэта такое хуткае асяроддзе, у якім можна запускаць TypeScript-код без лішніх танцаў з бубнам.
Усё проста:
- Ідзем на сайт: https://bun.sh/
- Ставім — як звычайную праграму
- Гатова!
Bun дазваляе запускаць .ts файлы наўпрост, без папярэдняй кампiляцыi ў JS. Значыць — менш крокаў, менш галаўнога болю.
🐳 Docker
Каб захоўваць і шукаць эмбэдынгі, нам патрэбна база дадзеных. І мы будзем выкарыстоўваць Qdrant, якая запускаецца праз Docker.
Калі Docker яшчэ не ўсталяваны — ляцім сюды: 👉 Docker desktop.
Выбіраем “спампаваць” (не трэба нічога аплачваць!) — і ставім. (мы ж бясплатна ўсе робім).
🚦 Запускаем вектарную базу
Пасля ўсталёўкі Docker час зрабіць крок да запуску Qdrant. Для гэтага нам трэба код з гітхабу (Наш рэпазіторый). Бяром так:
https://github.com/bel-frontend/RAG (Спадзяюся што тут падрабязна распавядаць не трэба)
або проста ў тэрмінале камандай:
git clone https://github.com/bel-frontend/RAG
Пераходзім у тэчку з базай :
cd lesson1_phi4/qdrant
(Важна: усе дзеянні будуць выконвацца у тэчцы ўрока №1: lesson1_phi4)
Запускаем Docker:
docker compose up -d
Гатова. Можна праверыць, ці ўсё працуе:
docker ps
Убачыш нешта накшталт гэтага:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f57677d89200 qdrant/qdrant:latest "./entrypoint.sh" 14 hours ago Up 14 hours 0.0.0.0:6333-6334->6333-6334/tcp qdrant
І самае кайфавае — можаш зайсці ў браўзеры на http://localhost:6333/dashboard Там — прыгожы інтэрфейс, дзе ўсё відаць: дакументы, вектары, запыты.
📥 Дадаем дадзеныя
Цяпер база працуе, але яна пустая. Час яе “пакарміць”.
У спампаваным праекце ёсць тэчка pdf_documents — туды можна скідаць PDF-кі, з якіх ты хочаш атрымліваць адказы.
Дэталева код які мы выканаем можна паглядзець у спампаваным праекце ці на старонцы гітхабу
🧩 Ствараем калекцыю
Запускаем першы скрыпт (у тэчцы lesson1_phi4):
bun run create_collection.ts
На дашбордзе з’явіцца новая калекцыя test_collection. Гэта як асобная “скрыня” для нашых вектараў.
🔄 Эмбэдзім PDF-файлы
А цяпер — самае смачнае:
bun run embeddings.ts
Гэты скрыпт:
- прачытае ўсе PDF,
- разбівае тэкст на часткі,
- для кожнай часткі зробіць эмбэдынг,
- адправіць усё ў Qdrant.
⏳ Час выканання залежыць ад колькасці файлаў і хуткасці машыны. Можна якраз зрабіць сабе чай/каву ☕.
У кансолі будзе нешта накшталт:
Embedding document 10 of 10 Inserted points: { result: { operation_id: 3, status: "acknowledged", }, status: "ok", time: 0.002781666, }
Цяпер у цябе ёсць “разумная база дадзеных”, якая разумее сэнс тэксту, а не толькі словы. (Можна пабачыць у дашбордзе)
🤖 Падключаем LLM і глядзім на вынік
База працуе. Дадзеныя ўнутры. Што далей?
Цяпер мы падключаем моўную мадэль (у нашым выпадку — gemma3) і глядзім, як яна адказвае на пытанні з улікам кантэксту. Гэта як калі б ты перад экзаменам даў ШІ канспект — і папрасіў адказаць згодна з ім.
🔍 Код, які ўсё робіць
Усё адбываецца праз файл index.ts. Ён:
- Дасылае запыт у Qdrant,
- Атрымлівае фрагменты тэксту, звязаныя з запытам,
- Перадае гэтыя фрагменты ў LLM разам з тваім пытаннем,
- І мадэль адказвае, ужо ведаючы кантэкст.
Вось кавалак, які гэта робіць:
const promptQuery = "напішы мне прыклады якія ты ведаеш"; const res = await searchString(promptQuery); // пошук у базе ... const response = await ollama.chat({ model: "gemma3:27b", // мадэль messages: [ { role: "system", content: "Ты — эксперт. Адказвай па-беларуску і толькі на падставе прадстаўленых дадзеных." }, ...res.map((item) => ({ role: "system", content: item.text })), { role: "user", content: `Запыт карыстальніка: ${promptQuery}` } ] });
Можна думаць пра гэта так:
📄 Твой запыт ідзе ў базу → 🧠 база вяртае кантэкст → 🤖 мадэль чытае, аналізуе і адказвае.
Функцыя searchString(promptQuery) шукае найбольш рэлевантныя фрагменты тэксту на падставе эмбедынгаў. Знойдзеныя дакументы (у выглядзе масіва аб’ектаў з полем text) выкарыстоўваюцца як кантэкст для LLM.
Мадэлі перадаецца спіс паведамленняў:
- два паведамленні з роляй system вызначаюць паводзіны мадэлі: адказваць па-беларуску, як эксперт, і толькі на падставе прадстаўленых дадзеных;
- затым перадаюцца знойдзеныя фрагменты (з пошуку);
- у канцы — зыходны запыт карыстальніка.
Мадэль gemma3:12b, запушчаная праз ollama, адказвае з улікам усяго кантэксту. У кансолі выводзіцца сфармаваны адказ, які можна далей выкарыстоўваць або аналізаваць.
🧪 Параўнаем: з кантэкстам vs. без
✅ З кантэкстам
Response: Згодна з прадстаўленым тэкстам, вось прыклады, якія там згадваюцца: **1. Вызначэнне сэнтыменту твіту (Zero-shot, One-shot, Few-shot):** (І далей — спіс добрых prompt-практык, як ты і чакаў.)
Тут мадэль дакладна адказвае, бо атрымала “шпаргалку” — часткі тэксту, якія знайшла база.
❌ Без кантэксту:
Каб прааналізаваць розніцу, проста закоментуй перадачу фрагментаў у messages:
...res.map((item) => ({ role: "system", content: item.text, })),
І тады адказ будзе прыкладна такі:
Response: Прабачце, але вы не далі мне ніякіх дадзеных. Я не магу напісаць прыклады, таму што не ведаю, якія прыклады вас цікавяць і на аснове чаго іх ствараць. Калі ласка, дайце мне інфармацыю, на якую я магу спасылацца, або ўкажыце тэму, па якой вам патрэбныя прыклады. Я буду рады дапамагчы, калі атрымаю дадатковыя дадзеныя.
Што, у прынцыпе, справядліва. Мадэль — не чараўнік. Яна працуе з тым, што мае.
🎯 Вынік?
Зараз ты бачыў усё на свае вочы: з кантэкстам — мадэль разумная, без — як “дурачок у белым пальто”.
RAG сапраўды кардынальна паляпшае вынікі, калі трэба працаваць з канкрэтнымі дакументамі ці ўласнымі дадзенымі.
Ну што, зрабілі мы немалае. І, галоўнае — усё лакальна, сваімі рукамі. Без OpenAI, без ключоў, без “платных чароў”.
🔚 Што ў глабальным выніку?
✅ Сабралі працоўную RAG-сістэму: — phi-4 для эмбэдынгаў, — gemma3 для генерацыі адказаў, — Qdrant — вектарная база, — LangChain — каб усё злучыць.
✅ Пераканаліся, што з кантэкстам мадэль сапраўды разумная, а без — проста генератар выпадковых адказаў.
✅ І самае галоўнае — пачалі разумець, як уся гэта магія працуе знутры.
⸻
🚀 Што далей?
А далей — яшчэ цікавей. У наступных артыкулах:
📌 Паглядзім, як пісаць добрыя prompt-ы, 📌 Патэсцім іншыя лакальныя мадэлі, 📌 Зробім інтэграцыю з UI або Telegram-ботам, 📌 І — магчыма — навучымся рабіць свае эмбэдынгі на аснове іншых мадэляў.
🙌 PS:
Дзякуй, што дачытаў(-ла) да канца! Калі матэрыял быў карысны — будзем вельмі рады, калі:
- 💬 Напішаш каментар ці пытанне,
- 📨 Падкінеш ідэю для наступнага артыкула,
- 🚀 Або проста падзелішся з сябрамі!
Тэхналогіі становяцца бліжэй, калі іх разумець. І ты ўжо зрабіў(ла) першы важны крок 💪
Да сустрэчы ў наступным артыкуле! Дзякуй вам за падтрымку!
Каментары
(Каб даслаць каментар залагуйцеся ў свой уліковы запіс)