Реализация AI-поиска по архиву документов (Document Search)
AI-поиск по документальному архиву позволяет находить документы по смыслу запроса — не только по ключевым словам в названии файла. «Договоры с условием автопролонгации, истекающие в 2025 году» — такой запрос решает AI-поиск, но не файловая система.
Индексирование архива
Каждый документ при попадании в архив проходит обработку:
- Извлечение текста: pdfminer (PDF), python-docx (DOCX), unstructured.io (все форматы)
- Структурирование: разбивка на чанки + сохранение метаданных (раздел, страница)
-
Эмбеддинги:
text-embedding-3-small(OpenAI) илиcointegrated/rubert-tiny2(on-premise) - Индексирование в Qdrant/pgvector
- Извлечение структурированных метаданных: тип документа, стороны, даты, суммы → в реляционную БД
Гибридный поиск
Комбинация полнотекстового и семантического поиска:
def search_documents(query: str, filters: dict = None) -> list[SearchResult]:
# Семантический поиск
query_embedding = embedder.encode(query)
semantic_results = qdrant.search(
collection_name="documents",
query_vector=query_embedding,
query_filter=build_qdrant_filter(filters),
limit=20
)
# BM25 поиск
bm25_results = elasticsearch.search(
index="documents",
body={"query": {"match": {"content": query}}, "filter": build_es_filter(filters)},
size=20
)
# RRF слияние и reranking
merged = reciprocal_rank_fusion(semantic_results, bm25_results)
reranked = cross_encoder.rerank(query, merged[:10])
return reranked[:5]
Фасетный поиск
Дополнительные фильтры для точного поиска:
- Тип документа: договор / акт / накладная
- Контрагент: название или ИНН
- Диапазон дат (подписания, окончания)
- Диапазон сумм
- Статус: действующий / расторгнут / истёк
Conversational search
«Найди договоры» → «с каким контрагентом?» → «Газпром» → «за какой период?» — диалоговый уточняющий поиск. LLM конвертирует диалог в структурированный запрос к хранилищу.
Метрики: NDCG@5, MRR, пользовательская оценка «нашли ли то что искали» (explicit feedback).







