Self-Query RAG: автоматичне генерування фільтрів LLM для точного пошуку
Уявіть: ви шукаєте «політики безпеки за минулий рік» у корпоративній базі з 15 000 документів. Звичайний RAG видає всі документи за семантикою «безпека» — включно з архівними регламентами п'ятирічної давності. Користувач тоне в нерелевантних результатах. Self-Query RAG вирішує це: LLM аналізує запит і автоматично будує фільтр doc_type=policy AND year>=поточний_рік-1 AND status=active, застосовуючи його разом з векторним пошуком. Precision@5 зростає з 0.68 до 0.89, частка архівних документів падає з 42% до 3% (зниження у 14 разів). Користувацька задоволеність зросла у 1.3 раза (з 72% до 94%).
Ми впроваджуємо Self-Query RAG під ключ — від розмітки метаданих до деплою асистента. Наші інженери адаптують рішення під будь-який стек: LangChain, Qdrant, Pinecone, Weaviate. Отримайте консультацію — розповімо деталі під ваш сценарій. Вартість проектів розраховується індивідуально залежно від об'єму даних та складності. Зменшення витрат на підтримку бази знань до 25% дає значну економію для компанії з 500 співробітників.
Огляд та технічна реалізація
Як Self-Query вирішує проблему фільтрації?
Без Self-Query запит «регламенти HR відділу» шукає всі документи за словом «регламент» і «HR», не фільтруючи за відділом. Ви отримуєте регламенти IT, Legal і навіть маркетингові інструкції. Self-Query змушує LLM витягти фільтр department=hr AND doc_type=regulation і відсікти все зайве на рівні сховища. Це дає економію часу пошуку та знижує вартість обробки запитів за рахунок точності. Компанії економлять до 40% часу на пошук документів і знижують витрати на підтримку бази знань на 25%.
Порівняння зі звичайним RAG
| Метрика | Звичайний RAG | Self-Query RAG |
|---|---|---|
| Precision@5 | 0.68 | 0.89 |
| Частка архівних документів | 42% | 3% |
| Середній час на пошук | 2.1 с | 2.3 с (через LLM-крок) |
| Користувацька задоволеність | 72% | 94% |
Self-Query RAG в 1.3 раза точніший за звичайний RAG за precision@5.
Чому Self-Query — must have для баз з метаданими?
Корпоративні бази знань містять документи різних типів, відділів і статусів. Без фільтрації користувачі отримують мішанину. Self-Query автоматично класифікує запит і застосовує релевантні метадані. Це особливо важливо для юридичних, HR та фінансових документів, де точність критична. Використання атрибутивних фільтрів та структурованих метаданих дозволяє значно підвищити точність семантичного пошуку.
Метадані та налаштування
| Поле | Тип | Приклад значення |
|---|---|---|
| doc_type | string | policy, contract, faq |
| department | string | hr, legal, it |
| year | integer | 2023, поточний рік |
| status | string | active, archived |
| author | string | Іванов І.І. |
Опис метаданих для LLM — критичний етап. Використовуйте AttributeInfo з чітким описом кожного поля.
Реалізація з LangChain
from langchain.retrievers.self_query.base import SelfQueryRetriever from langchain.chains.query_constructor.base import AttributeInfo from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_community.vectorstores import Qdrant metadata_field_info = [ AttributeInfo( name="doc_type", description="Тип документа: contract, regulation, policy, faq, procedure", type="string", ), AttributeInfo( name="department", description="Відділ або підрозділ: hr, legal, finance, it, security", type="string", ), AttributeInfo( name="year", description="Рік публікації документа", type="integer", ), AttributeInfo( name="status", description="Статус документа: active, archived, draft", type="string", ), AttributeInfo( name="author", description="Автор або відповідальний за документ", type="string", ), ] document_content_description = "Корпоративна документація компанії: регламенти, політики, договори, процедури" llm = ChatOpenAI(model="gpt-4o", temperature=0) embeddings = OpenAIEmbeddings(model="text-embedding-3-small") retriever = SelfQueryRetriever.from_llm( llm=llm, vectorstore=vectorstore, document_contents=document_content_description, metadata_field_info=metadata_field_info, enable_limit=True, verbose=True, ) Приклад роботи Self-Query
# Приклад 1: Фільтр за роком і типом result = retriever.invoke( "Які політики безпеки діяли минулого року?" ) # LLM генерує фільтр: {"doc_type": "policy", "department": "security", "year": минулий_рік, "status": "active"} # Приклад 2: Фільтр за відділом result = retriever.invoke( "Покажи регламенти HR відділу" ) # Фільтр: {"doc_type": "regulation", "department": "hr"} # Приклад 3: Без фільтра (звичайний векторний пошук) result = retriever.invoke( "Як підготуватися до аудиту?" ) # LLM не видобуває структурованих фільтрів — чистий semantic search Кастомна реалізація без LangChain
from pydantic import BaseModel, Field from typing import Optional from openai import OpenAI import json class SearchFilter(BaseModel): semantic_query: str = Field(description="Чисто семантична частина запиту для векторного пошуку") doc_type: Optional[str] = Field(default=None, description="Тип документа") department: Optional[str] = Field(default=None, description="Відділ") year_from: Optional[int] = Field(default=None, description="Рік від (включно)") year_to: Optional[int] = Field(default=None, description="Рік до (включно)") status: Optional[str] = Field(default=None, description="Статус: active/archived") def parse_query_to_filter(user_query: str, client: OpenAI) -> SearchFilter: response = client.beta.chat.completions.parse( model="gpt-4o-mini", messages=[{ "role": "system", "content": "Витягни із запиту користувача структуровані фільтри для пошуку документів." }, { "role": "user", "content": user_query }], response_format=SearchFilter, temperature=0, ) return response.choices[0].message.parsed def self_query_search(user_query: str, vectorstore, top_k: int = 5) -> list: filter_obj = parse_query_to_filter(user_query, openai_client) qdrant_filter = build_qdrant_filter(filter_obj) return vectorstore.similarity_search( filter_obj.semantic_query, k=top_k, filter=qdrant_filter, ) Кейси та впровадження
Практичний кейс: корпоративна база знань
Задача: пошуковий асистент для 15 000 внутрішніх документів з метаданими (тип, відділ, рік, статус, автор).
До Self-Query: 42% запитів повертали архівні документи замість актуальних. Після Self-Query (наш клієнт — компанія з 500+ співробітників):
- Архівні документи в результатах для «актуальних» запитів: 42% → 3% (зниження у 14 разів)
- Precision@5: 0.68 → 0.89
- Користувацька задоволеність: +31%
Failure cases: LLM іноді неправильно інтерпретує параметри фільтра при неоднозначних запитах. Рішення — додати confidence threshold і fallback на pure semantic search при низькій впевненості. При необхідності ми виконуємо fine-tuning промпту для покращення якості видобування фільтрів.
Коли Self-Query не приносить користі?
Якщо метадані документів бідні або нерозрізненні (наприклад, всі документи одного типу), Self-Query не дасть виграшу. У таких випадках достатньо звичайного семантичного пошуку. Ми завжди проводимо попередній аудит даних.Покроковий план впровадження
- Аудит документів і метаданих — визначаємо поля для фільтрації.
- Розмітка або автоматичне видобування метаданих (NLP-класифікація).
- Вибір векторної БД і налаштування індексації.
- Розробка промпту для LLM та інтеграція Self-Query Retriever.
- A/B тестування і підбір порогів фільтрації.
Що входить в роботу
- Документація: схема метаданих, опис промпту, інструкція з розширення.
- Доступи: розмежування прав користувачів через статуси документів.
- Навчання: 2 години для адміністраторів системи.
- Підтримка: 1 місяць після запуску.
Строки та вартість
- Розмітка метаданих: 1–3 тижні (залежить від наявності даних).
- Реалізація Self-Query Retriever: 3–5 днів.
- Тестування та підбір промпту: 3–5 днів.
- Разом: 2–5 тижнів. Вартість розраховується індивідуально — пишіть, оцінимо ваш проект.
Ми працюємо з RAG більше 5 років, виконали 30+ проектів. Гарантуємо прозору архітектуру та документацію. Отримайте консультацію — обговоримо деталі вашого завдання.
Джерело: Retrieval-augmented generation (Wikipedia).







