Розробка RAG з векторною базою даних Elasticsearch (kNN)

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

Elasticsearch з версії 8.x підтримує нативний пошук k-Nearest Neighbors на щільних векторах (поле dense_vector). Для команд, які вже використовують Elasticsearch як пошуковий рушій, це найприроднічий шлях до RAG — без додавання нової інфраструктури. Нативна інтеграція повнотекстового BM25 та векторного пошуку робить ES потужним вибором для гібридного пошуку.

Створення індексу з полем dense_vector

from elasticsearch import Elasticsearch

es = Elasticsearch("http://localhost:9200")

# Створення індексу з маппінгом
index_config = {
    "mappings": {
        "properties": {
            "content": {
                "type": "text",
                "analyzer": "russian",  # Нативна підтримка російської морфології
            },
            "source": {"type": "keyword"},
            "doc_type": {"type": "keyword"},
            "page": {"type": "integer"},
            "date": {"type": "date"},
            "embedding": {
                "type": "dense_vector",
                "dims": 1536,
                "index": True,
                "similarity": "cosine",
                # Параметри HNSW
                "index_options": {
                    "type": "hnsw",
                    "m": 16,
                    "ef_construction": 100,
                }
            }
        }
    },
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 1,
    }
}

es.indices.create(index="knowledge_base", body=index_config)

Індексування документів

from openai import OpenAI
from elasticsearch.helpers import bulk

openai_client = OpenAI()

def generate_actions(chunks: list):
    texts = [c["text"] for c in chunks]
    # Пакетні вкладення
    response = openai_client.embeddings.create(
        model="text-embedding-3-small",
        input=texts
    )
    embeddings = [e.embedding for e in response.data]

    for chunk, embedding in zip(chunks, embeddings):
        yield {
            "_index": "knowledge_base",
            "_source": {
                "content": chunk["text"],
                "source": chunk["source"],
                "doc_type": chunk["doc_type"],
                "page": chunk.get("page", 0),
                "embedding": embedding,
            }
        }

# Пакетне завантаження
bulk(es, generate_actions(document_chunks))

Гібридний пошук: BM25 + kNN

Elasticsearch підтримує гібридний пошук через knn + query в одному запиті:

def hybrid_search_es(
    query: str,
    doc_type_filter: str = None,
    top_k: int = 5
) -> list:
    query_embedding = openai_client.embeddings.create(
        model="text-embedding-3-small",
        input=query
    ).data[0].embedding

    # Пункт фільтру
    filter_clause = []
    if doc_type_filter:
        filter_clause.append({"term": {"doc_type": doc_type_filter}})

    # Гібридний: kNN + BM25 через RRF
    body = {
        "query": {
            "bool": {
                "must": {
                    "match": {
                        "content": {
                            "query": query,
                            "analyzer": "russian"
                        }
                    }
                },
                "filter": filter_clause,
            }
        },
        "knn": {
            "field": "embedding",
            "query_vector": query_embedding,
            "k": top_k * 3,  # Розширена множина для злиття
            "num_candidates": 100,
            "filter": filter_clause,
        },
        "rank": {
            "rrf": {
                "window_size": 50,
                "rank_constant": 20,
            }
        },
        "size": top_k,
        "_source": ["content", "source", "doc_type"],
    }

    response = es.search(index="knowledge_base", body=body)
    return [
        {
            "text": hit["_source"]["content"],
            "source": hit["_source"]["source"],
            "score": hit["_score"],
        }
        for hit in response["hits"]["hits"]
    ]

Перевага: російська морфологія з коробки

Elasticsearch з аналізатором russian підтримує стемінг російських слів через Snowball. Це критично для частини BM25 гібридного пошуку — запит «договором» знайде документи з «договор», «договоры», «договорам».

# Тест морфологічного аналізу
es.indices.analyze(
    index="knowledge_base",
    body={"analyzer": "russian", "text": "договором аренды"}
)
# tokens: ["договор", "аренд"] — стемовані форми

Практичний кейс: міграція існуючого Elasticsearch до RAG

Контекст: Компанія використовує ES 8.x як пошуковик для 500K документів. Завдання: додати RAG поверх без зміни інфраструктури.

Кроки:

  1. Додати поле embedding (dense_vector, dims=1536) до існуючого маппінгу
  2. Пакетна векторизація існуючих документів (2 дні, 500K × $0.02/1M = $10)
  3. Переіндексування з новим полем (6 годин)
  4. Додавання RRF злиття до пошукових запитів
  5. Рівень RAG поверх пошуку ES

Результати (vs чистий BM25):

  • NDCG@5: 0.64 → 0.81
  • Recall@10: 0.71 → 0.88
  • Latency P95: 85ms → 140ms (гібридний)
  • Faithfulness (RAGAS): 0.76 → 0.91

Перехід від чистого BM25 до гібридного kNN+BM25 дав +27% до NDCG без зміни інфраструктури.

Часові рамки

  • Додавання векторного поля + переіндексування: 2–5 днів
  • Розроблення гібридних пошукових запитів: 3–5 днів
  • RAG pipeline та оцінка: 1–2 тижні
  • Всього: 2–4 тижні