Представьте: вы ищете «политики безопасности за прошлый год» в корпоративной базе из 15 000 документов. Обычный RAG выдаёт все документы по семантике «безопасность» — включая архивные регламенты пятилетней давности. Пользователь тонет в нерелевантных результатах. Self-Query RAG решает это: LLM анализирует запрос и автоматически строит фильтр doc_type=policy AND year>=текущий_год-1 AND status=active, применяя его вместе с векторным поиском. Precision@5 вырастает с 0.68 до 0.89, доля архивных документов падает с 42% до 3%.
Мы внедряем Self-Query RAG под ключ — от разметки метаданных до деплоя ассистента. Наши инженеры адаптируют решение под любой стек: LangChain, Qdrant, Pinecone, Weaviate. Получите консультацию — расскажем детали под ваш сценарий.
Как 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 и финансовых документов, где точность критична.
Примеры метаданных для Self-Query
| Поле | Тип | Пример значения |
|---|---|---|
| doc_type | string | policy, contract, faq |
| department | string | hr, legal, it |
| year | integer | 2023, 2024 |
| status | string | active, archived |
| author | string | Иванов И.И. |
Реализация через LangChain SelfQueryRetriever
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 # Описание метаданных для LLM 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 Кастомная реализация Self-Query без 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%
- Precision@5: 0.68 → 0.89
- Пользовательская удовлетворённость: +31%
Failure cases: LLM иногда неверно интерпретирует параметры фильтра при неоднозначных запросах. Решение — добавить confidence threshold и fallback на pure semantic search при низкой уверенности. При необходимости мы выполняем fine-tuning промпта для улучшения качества извлечения фильтров.
Когда Self-Query не приносит пользы?
Если метаданные документов бедны или неразличимы (например, все документы одного типа), 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+ проектов. Гарантируем прозрачную архитектуру и документацию. Получите консультацию — обсудим детали вашей задачи. Закажите демо — покажем на ваших данных.







