Розробка RAG з векторною базою даних Qdrant

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка RAG з векторною базою даних Qdrant
Середній
від 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

Розробка RAG з векторною базою даних Qdrant

Qdrant — відкрита векторна база даних, написана на Rust. Вирізняється високою продуктивністю, багатою системою фільтрації через payload, вбудованим гібридним пошуком та зручним REST/gRPC API. Доступна як керована хмара (Qdrant Cloud) та self-hosted. Один з найпопулярніших рішень для production RAG-систем.

Встановлення через Docker та підключення

docker pull qdrant/qdrant
docker run -p 6333:6333 -v $(pwd)/qdrant_storage:/qdrant/storage qdrant/qdrant
from qdrant_client import QdrantClient
from qdrant_client.models import (
    Distance, VectorParams, SparseVectorParams,
    SparseIndexParams, HnswConfigDiff
)

client = QdrantClient(url="http://localhost:6333")
# Або хмара
client = QdrantClient(url="https://cluster.qdrant.tech", api_key="...")

Створення колекції з dense та sparse векторами

from qdrant_client.models import VectorsConfig, SparseVectorsConfig

client.create_collection(
    collection_name="documents",
    vectors_config={
        "dense": VectorParams(
            size=1536,
            distance=Distance.COSINE,
            hnsw_config=HnswConfigDiff(m=16, ef_construct=200)
        )
    },
    sparse_vectors_config={
        "sparse": SparseVectorParams(
            index=SparseIndexParams(on_disk=False)
        )
    }
)

Індексація з payload-метаданими

from qdrant_client.models import PointStruct, SparseVector
from fastembed import SparseTextEmbedding, TextEmbedding
import uuid

dense_model = TextEmbedding("sentence-transformers/paraphrase-multilingual-mpnet-base-v2")
sparse_model = SparseTextEmbedding("prithivida/Splade_PP_en_v1")

def index_chunks(chunks: list) -> None:
    points = []
    for chunk in chunks:
        # Dense embedding
        dense_vec = list(dense_model.embed([chunk.text]))[0].tolist()

        # Sparse embedding (SPLADE)
        sparse_output = list(sparse_model.embed([chunk.text]))[0]

        point = PointStruct(
            id=str(uuid.uuid4()),
            vector={
                "dense": dense_vec,
                "sparse": SparseVector(
                    indices=sparse_output.indices.tolist(),
                    values=sparse_output.values.tolist()
                )
            },
            payload={
                "text": chunk.text,
                "source": chunk.source,
                "doc_type": chunk.doc_type,
                "page": chunk.page,
                "date": chunk.date,
                "department": chunk.department,
            }
        )
        points.append(point)

    client.upsert(collection_name="documents", points=points)

Гібридний пошук з RRF

from qdrant_client.models import Prefetch, FusionQuery, Fusion, Filter, FieldCondition, MatchValue

def hybrid_search(
    query: str,
    doc_type: str = None,
    top_k: int = 5
) -> list:
    # Векторы для запиту
    dense_vec = list(dense_model.embed([query]))[0].tolist()
    sparse_output = list(sparse_model.embed([query]))[0]
    sparse_vec = SparseVector(
        indices=sparse_output.indices.tolist(),
        values=sparse_output.values.tolist()
    )

    # Фільтр за метаданими
    query_filter = None
    if doc_type:
        query_filter = Filter(
            must=[FieldCondition(key="doc_type", match=MatchValue(value=doc_type))]
        )

    # Гібридний пошук з RRF fusion
    results = client.query_points(
        collection_name="documents",
        prefetch=[
            Prefetch(query=dense_vec, using="dense", limit=30, filter=query_filter),
            Prefetch(query=sparse_vec, using="sparse", limit=30, filter=query_filter),
        ],
        query=FusionQuery(fusion=Fusion.RRF),
        limit=top_k,
        with_payload=True,
    )

    return [
        {"text": r.payload["text"], "source": r.payload["source"], "score": r.score}
        for r in results.points
    ]

Практичний кейс: RAG для e-commerce підтримки

Завдання: багатомовний помічник підтримки інтернет-магазину (рус/англ), 85 000 чанків (FAQ, політики, описи товарів).

Стек: Qdrant self-hosted (Docker), SPLADE для sparse, paraphrase-multilingual-mpnet-base-v2 для dense, GPT-4o-mini для генерації.

Результати гібридного vs лише dense:

Метрика Лише dense Гібридний (RRF)
MRR@5 0.71 0.84
NDCG@5 0.68 0.81
Faithfulness 0.82 0.91
Latency P95 95мс 140мс

Гібридний пошук дає +13% до MRR за рахунок точного BM25-matching на номерах замовлень, артикулах товарів та конкретних термінах.

Фільтрація через payload-індекси

Для прискорення фільтрації створюємо payload-індекси:

from qdrant_client.models import PayloadSchemaType

client.create_payload_index(
    collection_name="documents",
    field_name="doc_type",
    field_schema=PayloadSchemaType.KEYWORD,
)

client.create_payload_index(
    collection_name="documents",
    field_name="date",
    field_schema=PayloadSchemaType.DATETIME,
)

Строки

  • Налаштування Qdrant + схема колекції: 1–2 дні
  • Ingestion pipeline (dense + sparse): 3–7 днів
  • Гібридний пошук + фільтрація: 3–5 днів
  • Оцінка та оптимізація: 1–2 тижні
  • Всього: 2–4 тижні