Как улучшить качество поиска для японского текста с помощью Sudachi, Milvus/Zilliz и AWS Bedrock
Этот пост был изначально опубликован на Qiita и переведен и опубликован здесь с разрешения.
Введение
Когда я начал создавать системы Retrieval-Augmented Generation (RAG) для японских пользователей, я столкнулся с проблемой, которая, вероятно, знакома каждому, кто работал с японским текстом: точность поиска здесь далеко не так проста, как в английском. У языка есть свои особенности — орфографические варианты, долгие гласные, смешанные письменности, различия поверхностных форм, — которые регулярно ломают как плотные, так и разреженные методы поиска, если использовать их по отдельности.
Плотный векторный поиск отлично справляется с пониманием контекста и семантического сходства, но быстро дает сбой, когда нужны точные совпадения — номера моделей, идентификаторы статей законов, внутренние коды или очень конкретные сущности вроде “金商法第37条 (Article 37 of the Financial Instruments and Exchange Act).” Методы на основе ключевых слов, такие как BM25, хорошо обрабатывают такие случаи, но они не справляются, когда входные данные содержат небольшие варианты написания (“サーバー” и “サーバ”) или когда одна и та же идея может быть выражена в нескольких формах.
Чтобы обойти это, я построил гибридный поисковый конвейер, который объединяет сильные стороны обоих подходов. Решение использует:
Sudachi: японский токенизатор, который обеспечивает нормализацию и стабильную токенизацию в текстах с несогласованностями.
Zilliz Cloud (полностью управляемый сервис Milvus): высокопроизводительная векторная база данных, поддерживающая плотные векторы, разреженные векторы и даже автоматическую генерацию векторов BM25, что значительно упрощает реализацию гибридного поиска.
AWS Bedrock: используется для генерации высококачественных плотных эмбеддингов (Titan Embeddings v2), которые образуют семантическую часть поискового конвейера.
В этом посте я покажу, как я объединил эти компоненты, чтобы создать высокоточное гибридное поисковое решение для японского языка. Я также включу практический пример, чтобы вы могли самостоятельно попробовать тот же рабочий процесс и адаптировать его для своих RAG-проектов.
Обзор архитектуры
Гибридная поисковая система в этой статье построена на простом, но эффективном стеке. Каждый компонент решает конкретную проблему, возникающую при работе с японским текстом, а вместе они формируют поисковый конвейер, который сочетает семантическое понимание с точностью точных совпадений. Ниже показано, как выглядит стек и почему важна каждая его часть.
SudachiPy — токенизатор / морфологический анализ
Японский текст часто содержит непоследовательные варианты написания, нерегулярные пробелы и вариации в нотации. Вместо того чтобы полагаться на наивную токенизацию, я использую SudachiPy и его API normalized_form(), чтобы всё это очистить. Это гарантирует, что “サーバー” и “サーバ” сопоставляются с одним и тем же нормализованным токеном, а документы, которые иначе были бы пропущены, всё равно появляются в результатах поиска. Один этот шаг резко повышает полноту поиска по всем направлениям.
Zilliz Cloud (Managed Milvus): высокопроизводительная векторная база данных
Milvus — самая широко используемая open-source векторная база данных, с 43K+ звездами на GitHub и большой экосистемой контрибьюторов. Zilliz Cloud использует то же ядро Milvus, но устраняет всю операционную работу — настройку кластера, автомасштабирование, оптимизацию производительности, резервное копирование, обновления версий — при этом сохраняя тот же API Milvus. На практике это означает, что я могу разрабатывать локально с open-source Milvus и развернуть точно такой же код в Zilliz Cloud, когда мне понадобится среда промышленного уровня.
Это важно, потому что многие проекты векторного поиска сталкиваются с одной и той же стеной: прототип работает, но масштабирование становится слишком дорогим или слишком непредсказуемым. Полностью управляемые PaaS-сервисы поиска, такие как Azure AI Search, или проприетарные векторные хранилища часто становятся узким местом по стоимости задолго до того, как достигаются требования к производительности. Zilliz Cloud предлагает более эффективный путь: более высокая пропускная способность, меньшая задержка и больший контроль над размещением данных — без роста затрат, который обычно проявляется при масштабировании.
В этой архитектуре Zilliz Cloud обрабатывает всё хранение и извлечение эмбеддингов. Он поддерживает:
Плотный векторный поиск для семантического сходства
Разреженный векторный поиск для поиска на основе ключевых слов
Начиная с Milvus v2.4, база данных также включает функцию Function, которая автоматически генерирует разреженные векторы BM25 из исходного текста. Это большое операционное преимущество. Мне не нужно вычислять BM25 на стороне клиента, поддерживать дополнительные конвейеры индексирования или синхронизировать метаданные между несколькими системами. Всё — от плотных эмбеддингов до BM25 и гибридного ранжирования — находится в одной базе данных, что делает весь рабочий процесс извлечения простым, быстрым и удобным в поддержке.
AWS Bedrock (Titan Embeddings v2): модель эмбеддингов
Для плотных векторных эмбеддингов я использую Titan Embeddings v2 от AWS Bedrock. Она хорошо работает с несколькими языками и надежно обрабатывает японский текст, что важно, когда вы создаете эмбеддинги для смешанного контента, такого как короткие запросы, длинные документы с политиками, описания продуктов и тексты в стиле FAQ.
Reciprocal Rank Fusion (RRF): метод переранжирования
Гибридный поиск работает только в том случае, если вы можете осмысленно объединять результаты плотного и разреженного поиска, а эти два пространства оценок фундаментально различаются. RRF (Reciprocal Rank Fusion) элегантно решает эту задачу, объединяя результаты на основе ранга, а не сырых оценок. Он дает стабильные и понятные гибридные результаты без ручной настройки весов или трюков с нормализацией.
Руководство по гибридному поиску для начинающих
Разобравшись с архитектурой, перейдем к тому, что вы действительно можете запустить. Я подготовил GitHub repo со всем кодом и примерными данными, которые вам нужны, поэтому настройка намеренно сделана легковесной. Как только вы запустите бесплатный кластер Zilliz Cloud и добавите свой API-ключ AWS Bedrock, вы сможете протестировать три режима извлечения бок о бок:
Плотный векторный поиск
Разреженный (BM25) полнотекстовый поиск
Гибридный поиск (слияние RRF)
Весь рабочий процесс выполняется с низкими затратами — платными являются только вызовы Bedrock для эмбеддингов.
Шаг 1: клонируйте репозиторий из GitHub
Сначала клонируйте репозиторий:
git clone [https://github.com/Beginnersguide138/rag-with-sudachi.git](https://github.com/Beginnersguide138/rag-with-sudachi.git)
Перейдите в директорию проекта и настройте окружение Python:
cd rag-with-sudachi
uv sync # Install Python dependencies using uv
cp .env.example .env # Create an environment file based on the template
Шаг 2: настройте Zilliz Cloud (бесплатный тариф)
Zilliz Cloud работает на всех основных облачных провайдерах — AWS, GCP и Azure. Вы можете зарегистрироваться напрямую на сайте Zilliz или оформить подписку через соответствующие облачные маркетплейсы. В этом руководстве я буду использовать путь через AWS Marketplace, поскольку это быстрый способ развернуть полностью управляемый кластер Milvus, не занимаясь инфраструктурой.
- Перейдите к листингу Zilliz Cloud на AWS Marketplace и нажмите “Try for free.” Это создаст бесплатный serverless-кластер Milvus:
Он никогда автоматически не перейдет на платный тариф
Имеет некоторые ограничения (например, ограниченные функции мониторинга)
Кластер более чем достаточен для этого руководства по гибридному поиску
2. Откройте консоль Zilliz Cloud после завершения подписки:
Создайте новую Organization (просто логический контейнер для ваших проектов).
Вы увидите уже подготовленный бесплатный serverless-кластер.
Возьмите Cluster Endpoint и API Key — они понадобятся вам при подключении из вашего кода.
Шаг 3: Настройте переменные окружения
Вставьте свои учетные данные Zilliz и Bedrock в файл .env:
# Zilliz Cloud connection
ZILLIZ_CLOUD_URI=https://your-cluster-id.serverless.region.cloud.zilliz.com
ZILLIZ_CLOUD_API_KEY=your-api-key-here
# AWS Bedrock short-term API key
AWS_BEARER_TOKEN_BEDROCK=bedrock-api-key-your-token-here
Примечание к коду: краткосрочные токены Bedrock истекают каждые 12 часов. Это сделано намеренно — они уменьшают радиус поражения при раскрытии учетных данных и идеально подходят для локальной разработки.
Шаг 4: Запустите Notebook или выполните скрипт
Откройте репозиторий в VS Code. Основное руководство находится в:
notebooks/hybrid_search_with_bm25.ipynb
Если вы предпочитаете чистый Python-процесс вместо Jupyter Notebook, вы можете выполнить:
python run_hybrid_search.py
Обе версии:
Создают схему Milvus
Применяют нормализацию Sudachi
Вставляют плотные и разреженные векторы
Сравнивают результаты семантического, ключевого и гибридного поиска
Технические детали
1. Ключ к обработке японского языка: нормализация текста с помощью Sudachi
В поисковых системах для японского контента значительная часть точности зависит от того, как текст предварительно обрабатывается во время индексации. Текст, извлеченный из PDF, часто содержит непоследовательные пробелы, орфографические вариации или шум, что нередко приводит к пропущенным совпадениям и более низкой полноте.
Чтобы решить эту проблему, в этой реализации используется Sudachi’s normalization function. Этот процесс стандартизирует токены перед индексацией, чтобы поисковая система могла рассматривать разные написания и представления как эквивалентные.
Код: обертка нормализации Sudachi
class SudachiAnalyzer:
def __init__(self):
self.tokenizer = dictionary.Dictionary(dict="core").create()
self.mode = tokenizer.Tokenizer.SplitMode.C
def analyze(self, text: str) -> str:
if not text:
return ""
tokens = self.tokenizer.tokenize(text, self.mode)
# Return as a space-separated string
return " ".join(\[t.normalized_form() for t in tokens if t.surface().strip()\])
analyzer = SudachiAnalyzer()
Почему нормализация важна
Использование normalized_form() унифицирует такие варианты, как:
Катакана: 「サーバー」 ⇔ 「サーバ」
Числовая запись: 「第1条」 ⇔ 「第一条」
Шум пробелов из PDF: 「第 一 条」(不自然なスペース) ⇔ 「第一条」
Без нормализации эти вариации приводят к:
Пропущенным совпадениям BM25
Некорректной токенизации разреженных векторов
Более низкой полноте для юридически структурированных запросов
Нормализуя и документы, и запросы, гибридная система значительно увеличивает вероятность совпадения.
2. Проектирование схемы в Zilliz Cloud (управляемый Milvus)
Milvus, ядро Zilliz Cloud, предоставляет функцию Function (доступную в v2.4 и более поздних версиях), которая автоматически генерирует разреженные векторы на основе BM25 в базе данных. Это устраняет необходимость предварительно вычислять векторы BM25 на стороне клиента.
Определение схемы
# Create schema (auto ID disabled for explicit ID assignment)
schema = MilvusClient.create_schema(auto_id=False, enable_dynamic_field=True)
# Field definitions
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(
field_name="text",
datatype=DataType.VARCHAR,
max_length=65535,
enable_analyzer=True,
analyzer_params={
"tokenizer": "whitespace"
}, # Sudachi already provides whitespace-separated input
)
schema.add_field(
field_name="dense_vector", datatype=DataType.FLOAT_VECTOR, dim=1024
) # Titan Embeddings v2 outputs 1024 dimensions
schema.add_field(field_name="sparse_vector", datatype=DataType.SPARSE_FLOAT_VECTOR)
# Define the BM25 function
bm25_function = Function(
name="text_bm25_emb",
input_field_names=\["text"\],
output_field_names=\["sparse_vector"\],
function_type=FunctionType.BM25,
)
schema.add_function(bm25_function)
Такая архитектура устраняет необходимость явно передавать разреженные векторы при вставке данных, значительно снижая операционную сложность.
Перенеся генерацию векторов BM25 в сам Milvus:
Конвейер загрузки данных становится проще
Явный расчет разреженных векторов не требуется
Вы избегаете поддержки дополнительного кода предварительной обработки
Масштабирование становится значительно проще
Это существенно снижает операционную нагрузку.
Проектирование индексов и стратегия оптимизации
# Index definitions
index_params = client.prepare_index_params()
index_params.add_index(
field_name="dense_vector", index_type="HNSW", metric_type="COSINE"
)
index_params.add_index(
field_name="sparse_vector",
index_type="SPARSE_INVERTED_INDEX",
metric_type="BM25",
params={"inverted_index_algo": "DAAT_MAXSCORE"},
)
Индекс плотных векторов: HNSW
HNSW (Hierarchical Navigable Small World) — это графовый ANN-алгоритм, широко используемый в векторных базах данных. Он обеспечивает:
Высокоскоростной поиск
Высокую полноту
Стабильную производительность при масштабировании
COSINE используется в качестве метрики сходства, поскольку Titan Embeddings работают в нормализованном косинусном пространстве.
Индекс разреженных векторов: инвертированный индекс с оптимизацией MaxScore
Разреженные векторы используют традиционную структуру инвертированного индекса. Дополнительная оптимизация DAAT_MAXSCORE обеспечивает:
Обработку «документ за документом» для эффективного обхода
Раннее отсечение документов, которые не могут достичь оценок top-k
Снижение вычислительных затрат без ущерба для точности
Это приводит к значительно более быстрому поиску BM25.
3. Реализация гибридного поиска с использованием RRF
Чтобы справедливо объединять результаты плотного (семантического) и разреженного (ключевого) поиска, система использует Reciprocal Rank Fusion (RRF). RRF устойчив, прост в применении и не требует настройки или нормализации между типами оценок.
Код гибридного поиска
from pymilvus import AnnSearchRequest, RRFRanker
def search_hybrid(client, collection_name, query_text, query_vector, top_k=5):
# Normalize and tokenize the query using Sudachi
query_processed = analyzer.analyze(query_text)
# Dense semantic search request
req_dense = AnnSearchRequest(
data=\[query_vector\],
anns_field="dense_vector",
param={"metric_type": "COSINE"},
limit=top_k * 2,
)
# Sparse BM25 keyword search request
req_sparse = AnnSearchRequest(
data=\[query_processed\],
anns_field="sparse_vector",
param={"metric_type": "BM25"},
limit=top_k * 2,
)
# Perform hybrid search using RRF
res = client.hybrid_search(
collection_name=collection_name,
reqs=\[req_dense, req_sparse\],
ranker=RRFRanker(), # Fuse rankings using RRF
limit=top_k,
output_fields=\["text", "original_text"\],
)
return res\[0\]
Сравнение фактических результатов поиска
В руководстве оцениваются результаты с использованием общедоступных документов Агентства финансовых услуг Японии. Ноутбук позволяет выполнять параллельное сравнение:
Семантического поиска (плотный вектор)
Полнотекстового поиска (разреженный вектор)
Гибридного поиска (плотный + разреженный через RRF)
Пример: запрос с высокой долей ключевых слов
Запрос: “指定ADR機関が存在しない場合の苦情処理措置”
Примечание: запрос означает «Процедура обработки жалоб в случае отсутствия назначенной организации ADR».
Результаты:
Поиск по плотным векторам: часто возвращает концептуально связанные фрагменты, но с трудом выводит точные нормативные положения.
Разреженный поиск BM25: корректно определяет документы, содержащие такие термины, как “designated ADR organization” и “complaint-handling measures,” и ранжирует их выше всего.
Гибридный поиск: сочетает способность BM25 к точному сопоставлению с дополнительным релевантным контекстом, полученным с помощью плотного поиска.
Это показывает, что поиск только по плотным векторам рискует пропустить критически важные результаты, когда пользователи формулируют запросы с использованием специализированной терминологии. Гибридный поиск крайне важен для поиска по бизнес-документам.
Резюме и области применения
В этой статье мы рассмотрели практическую настройку гибридного поиска, которая сочетает нормализацию на основе Sudachi с Zilliz Cloud (управляемым Milvus). Цель была простой: построить конвейер поиска, который хорошо работает с японским текстом, где важны и семантическая близость, и точное сопоставление. Благодаря объединению плотных векторов, разреженных векторов BM25 и объединения на основе RRF система остается точной, простой в эксплуатации и адаптируемой к реальным производственным нагрузкам.
Ключевые преимущества
Устойчивость к вариациям написания: нормализация Sudachi сглаживает орфографические различия, проблемы с пробелами и шум извлечения из PDF, предотвращая распространенные сбои полноты поиска в японском текстовом поиске.
Низкие операционные затраты: Milvus Functions обрабатывают генерацию разреженных векторов BM25 внутри базы данных. Никаких дополнительных задач предварительной обработки, внешнего поискового сервиса и дублирования логики индексирования.
Высокая общая точность: RRF объединяет плотный и разреженный поиск без сложной настройки весов. Вы получаете стабильные гибридные результаты, которые корректно обрабатывают как концептуальные запросы, так и точные идентификаторы.
Возможные сценарии использования
Этот гибридный подход особенно эффективен в сценариях, где пользователи могут переключаться между точными, структурированными запросами и открытой формулировкой:
Поиск по внутренним политикам и руководствам: поддерживает точные ссылки (например, номера статей), одновременно обрабатывая неопределенные или исследовательские запросы.
Поиск товаров в электронной коммерции: обеспечивает точный поиск по номеру детали, предлагая при этом рекомендации на основе сходства.
Базы знаний службы поддержки клиентов: сопоставляет структурированные термины, такие как коды ошибок, при этом интерпретируя естественный пользовательский ввод (“画面が真っ黒です”, “ログインできない”).
Полный исходный код и Jupyter Notebook, использованные в этой статье, доступны в следующем репозитории: GitHub: rag-with-sudachi
Стоимость тестирования всего минимальна — оплачиваются только вызовы embeddings AWS Bedrock. Бесплатного serverless-тарифа Zilliz Cloud достаточно для запуска всего рабочего процесса.
Если вы изучаете гибридный поиск для производственных систем или внутренних прототипов, этот пример — отличная отправная точка.
Читать далее
Milvus/Zilliz + Surveillance: How Vector Databases Transform Multi-Camera Tracking
See how Milvus vector database enhances multi-camera tracking with similarity-based matching for better surveillance in retail, warehouses and transport hubs.

Vector Databases vs. Time Series Databases
Use a vector database for similarity search and semantic relationships; use a time series database for tracking value changes over time.

Legal Document Analysis: Harnessing Zilliz Cloud's Semantic Search and RAG for Legal Insights
Enhance legal document analysis with Zilliz Cloud’s Semantic Search and RAG. Improve accuracy, efficiency, and scalability for contracts, case law, and compliance.



