Реализация Self-Query RAG с метаданными

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1566 услуг
Реализация Self-Query RAG с метаданными
Средний
от 1 дня до 3 дней
Часто задаваемые вопросы

Направления AI-разработки

Этапы разработки AI-решения

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    901
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1119
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    853

Реализация Self-Query RAG с метаданными

Self-Query RAG — техника, при которой LLM анализирует запрос пользователя и автоматически конструирует структурированный фильтр по метаданным в дополнение к векторному поиску. Вместо поиска только по семантике, система точечно фильтрует документы по дате, типу, автору, отделу и другим атрибутам.

Проблема без Self-Query

Без Self-Query запрос «политики безопасности, выпущенные в 2024 году» ищет все документы по семантике «безопасность», не фильтруя по году. Пользователь получает смешанные результаты разных периодов. С Self-Query: LLM извлекает фильтр date >= 2024-01-01 AND doc_type = "security_policy" и применяет его совместно с векторным поиском.

Реализация через 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,  # Позволяет LLM указать limit в запросе
    verbose=True,
)

Пример работы Self-Query

# Пример 1: Фильтр по году и типу
result = retriever.invoke(
    "Какие политики безопасности действовали в 2023 году?"
)
# LLM генерирует фильтр: {"doc_type": "policy", "department": "security", "year": 2023, "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
    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:

  • Архивные документы в результатах для «актуальных» запросов: 42% → 3%
  • Precision@5: 0.68 → 0.89
  • Пользовательская удовлетворённость: +31%

Failure cases: LLM иногда неверно интерпретирует параметры фильтра при неоднозначных запросах. Решение — добавить confidence threshold и fallback на pure semantic search при низкой уверенности.

Сроки

  • Разметка метаданных документов: 1–3 недели (зависит от наличия данных)
  • Реализация Self-Query Retriever: 3–5 дней
  • Тестирование и подбор промпта: 3–5 дней
  • Итого: 2–5 недель