Реалізація семантичного пошуку за текстовими документами

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Реалізація семантичного пошуку за текстовими документами
Середній
~3-5 днів
Часті запитання

Напрямки 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

Реалізація семантичного пошуку за текстовими документами

Семантичний пошук розуміє значення запиту, а не лише ключові слова. Запит "як підвищити мотивацію команди" знаходить документи про "методи управління персоналом", які не містять жодного слова з запиту. Це принципово відрізняється від BM25/TF-IDF.

Архітектура семантичного пошуку

Bi-encoder (основний режим роботи): окремі моделі кодують запити та документи у векторний простір. Пошук — це знаходження найближчих векторів через ANN (Approximate Nearest Neighbor).

Cross-encoder (переранжування): приймає пару запит+документ та виводить оцінку релевантності. Повільніше (O(N) проти O(log N)), але точніше. Застосовується для переранжування top-K результатів bi-encoder.

Комбінація bi-encoder (пошук) + cross-encoder (переранжування) — це стандарт для production-систем.

Моделі для російської мови

from sentence_transformers import SentenceTransformer, CrossEncoder

# Bi-encoder
bi_encoder = SentenceTransformer("cointegrated/rubert-tiny2")
# Для кращої якості: "sbert-base-ru-mean-tokens"

# Cross-encoder
cross_encoder = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")  # English
# Для російської: "DiTy/cross-encoder-russian-msmarco"

Векторне сховище та індекс

Qdrant — рекомендується для production:

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

client = QdrantClient("localhost", port=6333)
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(size=312, distance=Distance.COSINE),
)

# Індексування
embeddings = bi_encoder.encode(documents, batch_size=64, show_progress_bar=True)
client.upload_points("documents", [
    PointStruct(id=i, vector=emb.tolist(), payload={"text": doc})
    for i, (emb, doc) in enumerate(zip(embeddings, documents))
])

FAISS — для in-memory індексів, швидкий, не потребує зовнішнього сервісу:

import faiss
index = faiss.IndexFlatIP(312)  # Inner Product (cosine після нормалізації)
faiss.normalize_L2(embeddings)
index.add(embeddings)

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

Семантичний + BM25 — краще обох окремо:

# BM25 компонент (Elasticsearch або rank_bm25)
from rank_bm25 import BM25Okapi
bm25 = BM25Okapi([doc.split() for doc in corpus])

# Семантичний компонент
semantic_scores = cosine_similarity([query_emb], doc_embeddings)[0]

# RRF (Reciprocal Rank Fusion)
def rrf(bm25_ranks, semantic_ranks, k=60):
    scores = {}
    for rank, idx in enumerate(bm25_ranks):
        scores[idx] = scores.get(idx, 0) + 1/(k + rank)
    for rank, idx in enumerate(semantic_ranks):
        scores[idx] = scores.get(idx, 0) + 1/(k + rank)
    return sorted(scores, key=scores.get, reverse=True)

Розширення запитів та попередня обробка

Якість пошуку залежить від обробки запиту:

  • Виправлення орфографії: користувачі роблять опечатки
  • Розширення синонімів: "ДМС" → "добровільне медичне страхування"
  • Переписування запиту через LLM: "де купити ноут" → "ноутбук купити інтернет-магазин"

Метрики якості

  • NDCG@10: нормалізований знижений кумулятивний виграш
  • MAP (Mean Average Precision): середня точність за всіма запитами
  • MRR (Mean Reciprocal Rank): обернений ранг першого релевантного результату

Для оцінки потрібен набір запитів з розміченою релевантністю (qrels). Можна створити автоматично: GPT-4o генерує запитання для кожного документа, а документ — "золота" відповідь.

Продуктивність

Qdrant з HNSW індексом: < 10ms на запит при 1M векторів. FAISS IndexIVFFlat: < 5ms при 10M векторів. Вузьке місце зазвичай — генерування embedding запиту, а не сам пошук.