Як використовувати RAG системи для пошуку інформації в корпоративних документах: Proxy-Pointer метод

Стаття розглядає метод Proxy-Pointer для ефективного пошуку інформації в корпоративних документах за допомогою RAG систем

Корпоративні бази знань розростаються до сотень гігабайт PDF, Word-файлів і презентацій, і знайти потрібну відповідь серед тисяч сторінок — справжній головний біль. RAG (Retrieval-Augmented Generation) з Proxy-Pointer методом вирішує цю проблему: система не просто шукає за ключовими словами, а розуміє контекст запиту і повертає точні уривки з посиланням на джерело. На налаштування базової системи піде 2–3 години, а для старту потрібні Python 3.10+, доступ до OpenAI API або локальна модель Ollama, та векторна база даних Qdrant.

🛠️ Що знадобиться

  • Python 3.10+ із бібліотеками LangChain 0.3 та llama-index — основний фреймворк для побудови RAG-пайплайну; безкоштовний, встановлюється через pip
  • Qdrant (локально або хмарний tier) — векторна база даних для зберігання ембедингів документів; безкоштовний self-hosted варіант або безкоштовний хмарний план до 1 ГБ
  • OpenAI API або Ollama з моделлю nomic-embed-text — для генерації ембедингів та відповідей; OpenAI платний (≈$0.002/1K токенів), Ollama — повністю безкоштовний локальний варіант
  • FastAPI + Uvicorn — для створення REST-ендпоінту, щоб команда могла звертатися до системи через браузер або Slack-бота; безкоштовний
  • Тестовий набір корпоративних документів — PDF або DOCX файли (HR-політики, технічна документація, звіти), мінімум 5–10 файлів для перевірки точності

📋 Покрокова інструкція

Крок 1: Встановлення середовища та залежностей

Відкрий термінал і створи окремий проєкт: виконай mkdir rag-corporate && cd rag-corporate && python -m venv venv, потім активуй оточення командою source venv/bin/activate (на Windows: venv\Scripts\activate). Встанови всі потрібні пакети однією командою: pip install langchain==0.3.* qdrant-client llama-index fastapi uvicorn python-docx pypdf sentence-transformers. Якщо використовуєш Ollama замість OpenAI — завантаж його з офіційного сайту ollama.com, встанови, і виконай ollama pull nomic-embed-text && ollama pull mistral. Перевір установку: запусти Python і введи import langchain; print(langchain.__version__) — має вивестись версія 0.3.x.

Крок 2: Підготовка та чанкування корпоративних документів

Створи файл document_processor.py і реалізуй завантаження документів. Для PDF використай PyPDFLoader, для DOCX — Docx2txtLoader з LangChain. Ключова частина Proxy-Pointer методу — це особливе чанкування: кожен фрагмент тексту (chunk) повинен містити метадані-покажчик: назву файлу, номер сторінки та унікальний ID. Встанови розмір чанку chunk_size=512 і перекриття chunk_overlap=64 через RecursiveCharacterTextSplitter — це дає оптимальний баланс між контекстом і точністю. Додай до кожного чанку поле proxy_id у форматі filename_page_chunkindex, щоб пізніше система могла точно вказати, звідки взята відповідь.

Крок 3: Індексація документів у Qdrant із Proxy-метаданими

Запусти Qdrant локально через Docker: виконай docker run -p 6333:6333 qdrant/qdrant — контейнер підніметься за 10–15 секунд. У новому файлі indexer.py підключись до Qdrant: client = QdrantClient(host="localhost", port=6333), потім створи колекцію командою client.create_collection(collection_name="corporate_docs", vectors_config=VectorParams(size=768, distance=Distance.COSINE)). Для кожного чанку згенеруй ембединг через SentenceTransformer("intfloat/multilingual-e5-base") — ця модель добре працює з українськими та англійськими текстами одночасно. Завантаж вектори разом із метаданими (proxy_id, filename, page, text) у Qdrant через client.upsert(). Підводний камінь: якщо документи оновлюються, фільтруй за полем filename і видаляй старі вектори перед повторною індексацією.

Крок 4: Реалізація Proxy-Pointer пошуку та генерації відповіді

Створи файл rag_engine.py — це серце системи. Функція пошуку приймає запит користувача, конвертує його в ембединг тією ж моделлю, що й при індексації, та виконує client.search(collection_name="corporate_docs", query_vector=query_embedding, limit=5, with_payload=True). Отримані 5 найрелевантніших чанків — це твої “проксі-покажчики”. Далі сформуй промпт для LLM: передай знайдені уривки як контекст і додай системну інструкцію: “Відповідай виключно на основі наданого контексту. Після кожного твердження вказуй джерело у форматі [Файл: назва, Стор.: N].” Виклич OpenAI або Ollama API з цим промптом — у відповіді LLM автоматично проставить посилання на конкретні сторінки документів. Результат — структурована відповідь із вбудованими посиланнями на першоджерела.

Крок 5: Розгортання REST API та тестування системи

Створи main.py із FastAPI: визнач ендпоінт POST /query, який приймає JSON {"question": "Яка політика відпусток?"} і повертає {"answer": "...", "sources": [{"file": "hr_policy.pdf", "page": 12}]}. Запусти сервер командою uvicorn main:app --reload --port 8000 і відкрий браузер на http://localhost:8000/docs — там з’явиться автоматична Swagger-документація з формою для тестування. Надішли тестовий запит через Swagger: введи реальне питання зі своєї предметної галузі та перевір, чи відповідь дійсно посилається на правильні сторінки. Фінальний результат — працюючий API, який будь-який член команди може інтегрувати у Slack-бот, корпоративний портал або Telegram-асистент.

⚠️ Типові помилки та як їх уникнути

  • Використання різних моделей для індексації та пошуку — якщо індексував через multilingual-e5-base, а запит конвертуєш через OpenAI text-embedding-3, вектори несумісні і пошук поверне сміття; завжди зберігай назву моделі в конфігу і використовуй одну й ту саму скрізь
  • Надто великий розмір чанку (більше 1024 токенів) — LLM губиться у великих фрагментах і “розмиває” відповідь; тримай chunk_size у межах 400–600 токенів для корпоративних документів
  • Відсутність фільтрації за типом документа — якщо в базі є і HR-документи, і технічна документація, запит “яка процедура звільнення?” може витягнути технічні інструкції; додавай метаполе doc_type і фільтруй через Filter(must=[FieldCondition(key="doc_type", match=MatchValue(value="hr"))])
  • Ігнорування оновлення індексу — якщо документи змінились, але індекс не перебудований, система дає застарілі відповіді; налаштуй автоматичну перевірку хешу файлів і перебудовуй лише змінені документи

💡 Поради для кращого результату

По-перше, використовуй гібридний пошук: поєднуй векторний пошук із BM25 (повнотекстовий) через параметр search_params=SearchParams(hnsw_ef=128) у Qdrant — це підвищує точність на 15–20% для документів із специфічною термінологією та абревіатурами. По-друге, додай query expansion: перед пошуком попроси LLM згенерувати 3 альтернативні формулювання запиту і пошукай за всіма трьома, а потім об’єднай результати через reciprocal rank fusion — це вловлює документи, де тема описана іншими словами. По-третє, впровади кешування популярних запитів через Redis: зберігай пари (хеш запиту → відповідь) із TTL 24 години, це зменшить витрати на API у 3–5 разів для типових питань типу “як взяти відпустку”. По-четверте, для документів українською мовою обов’язково додай langdetect і налаштуй окремий промпт для україномовних запитів — це суттєво покращує якість відповідей порівняно з англомовним системним промптом.

❓ Часті запитання (FAQ)

1. Чим Proxy-Pointer метод відрізняється від звичайного RAG?
У класичному RAG система просто повертає знайдені фрагменти без прив’язки до джерела. Proxy-Pointer додає унікальний ідентифікатор до кожного чанку під час індексації, тому відповідь завжди містить точне посилання: файл, сторінку і навіть абзац. Це критично важливо для корпоративного середовища, де співробітники мають перевіряти першоджерело перед прийняттям рішень.

2. Скільки документів може обробити система без деградації якості?
Qdrant з HNSW-індексом стабільно працює до 10 мільйонів векторів на одному вузлі. Для корпоративної бази у 10 000 документів (≈5 мільйонів чанків) пошук займає менше 100 мс. Якщо база більша — розгортай Qdrant у кластерному режимі через Docker Compose з кількома шардами.

3. Чи можна запустити систему без OpenAI, щоб дані не виходили за межі компанії?
Так, і це навіть рекомендований підхід для чутливих корпоративних даних. Використовуй Ollama з моделлю mistral:7b або llama3.2:3b для генерації відповідей і nomic-embed-text для ембедингів — все працює локально, жодні дані не залишають корпоративну мережу.

4. Що робити, якщо система дає нерелевантні відповіді на специфічні технічні запити?
Проблема зазвичай у generic-моделі ембедингів. Розглянь fine-tuning моделі ембедингів на корпоративному словнику через бібліотеку sentence-transformers з парами (запит, релевантний уривок) — навіть 200–300 пар суттєво покращують точність для вузькоспеціалізованої лексики.

5. Як інтегрувати систему з корпоративним Slack або Teams?
Для Slack встанови slack-bolt SDK і підпишись на подію app_mention — коли хтось тегує бота, запит автоматично летить до твого FastAPI ендпоінту. Для Microsoft Teams використовуй Azure Bot Framework з вебхуком на той самий POST /query ендпоінт. Обидва варіанти налаштовуються за 1–2 години.

🏁 Підсумок

Ти навчився будувати повноцінну RAG-систему з Proxy-Pointer методом: від індексації корпоративних документів у Qdrant до розгортання API, який повертає відповіді з точними посиланнями на першоджерела. Результат — інструмент, який замінює години пошуку по папках на миттєві відповіді з підтвердженими джерелами.

Почни прямо зараз: візьми 5–10 реальних корпоративних документів, виконай кроки 1–3 для індексації та протестуй пошук через Qdrant Dashboard за адресою http://localhost:6333/dashboard ще до написання API — це покаже якість ембедингів і дасть впевненість перед повним розгортанням.

РОЗСИЛКА

📬 Щотижневий AI-дайджест

Найкращі статті про ШІ та автоматизацію — без спаму, лише суть

Без спаму · Відписатись будь-коли

Telegram