So verbessern Sie die Retrieval-Qualität für japanischen Text mit Sudachi, Milvus/Zilliz und AWS Bedrock
Dieser Beitrag wurde ursprünglich auf Qiita veröffentlicht und wird hier mit Genehmigung übersetzt und veröffentlicht.
Einführung
Als ich begann, Retrieval-Augmented Generation (RAG)-Systeme für japanische Nutzer zu entwickeln, stieß ich auf ein Problem, das wahrscheinlich jedem vertraut vorkommt, der mit japanischem Text gearbeitet hat: Die Suchgenauigkeit ist einfach nicht so unkompliziert wie im Englischen. Die Sprache hat Eigenheiten – orthografische Varianten, lange Vokale, gemischte Schriftsysteme, Unterschiede in Oberflächenformen –, die sowohl dichte als auch sparse Retrieval-Methoden regelmäßig scheitern lassen, wenn sie isoliert eingesetzt werden.
Dichte Vektorsuche eignet sich hervorragend, um Kontext und semantische Ähnlichkeit zu verstehen, bricht aber schnell ein, wenn man exakte Treffer benötigt – Modellnummern, Kennungen von Gesetzesartikeln, interne Codes oder sehr spezifische Entitäten wie „金商法第37条 (Artikel 37 des Financial Instruments and Exchange Act).“ Keyword-basierte Methoden wie BM25 bewältigen diese Fälle gut, können aber nicht mithalten, wenn die Eingabe kleine Schreibvarianten enthält („サーバー“ vs. „サーバ“) oder wenn dieselbe Idee in mehreren Formen ausgedrückt werden kann.
Um dies zu umgehen, habe ich eine hybride Suchpipeline entwickelt, die die Stärken beider Ansätze kombiniert. Die Lösung verwendet:
Sudachi: einen japanischen Tokenizer, der Normalisierung und stabile Tokenisierung über inkonsistente Texte hinweg bietet.
Zilliz Cloud (der vollständig verwaltete Milvus-Service): eine leistungsstarke Vektordatenbank, die dichte Vektoren, sparse Vektoren und sogar automatische BM25-Vektorgenerierung unterstützt, wodurch hybride Suche deutlich einfacher zu implementieren ist.
AWS Bedrock: wird verwendet, um hochwertige dichte Embeddings (Titan Embeddings v2) zu erzeugen, die die semantische Seite der Retrieval-Pipeline bilden.
In diesem Beitrag zeige ich, wie ich diese Bausteine zusammengeführt habe, um ein hochpräzises japanisches hybrides Suchsystem zu entwickeln. Außerdem füge ich ein praktisches Beispiel hinzu, damit Sie denselben Workflow selbst ausprobieren und an Ihre eigenen RAG-Projekte anpassen können.
Architekturüberblick
Das hybride Suchsystem in diesem Artikel basiert auf einem einfachen, aber effektiven Stack. Jede Komponente löst ein spezifisches Problem, das bei der Verarbeitung japanischer Texte auftritt, und gemeinsam bilden sie eine Retrieval-Pipeline, die semantisches Verständnis mit Präzision bei exakten Treffern ausbalanciert. Hier ist die Aufschlüsselung, wie der Stack aussieht und warum jeder Teil wichtig ist.
SudachiPy — Tokenizer / Morphologische Analyse
Japanischer Text enthält häufig inkonsistente Schreibweisen, Unregelmäßigkeiten bei Abständen und Variationen in der Notation. Anstatt mich auf naive Tokenisierung zu verlassen, verwende ich SudachiPy und dessen normalized_form()-API, um all dies zu bereinigen. Dadurch wird sichergestellt, dass „サーバー“ und „サーバ“ demselben normalisierten Token zugeordnet werden und Dokumente, die sonst übersehen würden, dennoch in den Suchergebnissen erscheinen. Dieser einzelne Schritt verbessert die Trefferabdeckung insgesamt drastisch.
Zilliz Cloud (Managed Milvus): Eine leistungsstarke Vektordatenbank
Milvus ist die am weitesten verbreitete Open-Source-Vektordatenbank, mit über 43.000 GitHub-Stars und einem großen Ökosystem von Mitwirkenden. Zilliz Cloud verwendet denselben Milvus-Kern, nimmt jedoch die gesamte operative Arbeit ab – Cluster-Einrichtung, Autoscaling, Performance-Tuning, Backups, Versions-Upgrades – und stellt dennoch dieselbe Milvus-API bereit. In der Praxis bedeutet das, dass ich lokal mit Open-Source-Milvus entwickeln und denselben Code exakt so in Zilliz Cloud bereitstellen kann, wenn ich eine produktionsreife Umgebung benötige.
Das ist wichtig, weil viele Vektorsuchprojekte an dieselbe Grenze stoßen: Der Prototyp funktioniert, aber die Skalierung wird zu teuer oder zu unvorhersehbar. Vollständig verwaltete PaaS-Suchdienste wie Azure AI Search oder proprietäre Vektorspeicher werden oft lange bevor die Leistungsanforderungen erfüllt sind zu Kostenengpässen. Zilliz Cloud bietet einen effizienteren Weg: höheren Durchsatz, geringere Latenz und mehr Kontrolle über das Datenlayout—ohne die Kostensteigerungen, die normalerweise bei Skalierung auftreten.
In dieser Architektur übernimmt Zilliz Cloud die gesamte Speicherung und den Abruf von Embeddings. Es unterstützt:
Dense-Vektorsuche für semantische Ähnlichkeit
Sparse-Vektorsuche für keywordbasierten Abruf
Ab Milvus v2.4 enthält die Datenbank außerdem eine Function-Funktion, die automatisch BM25-Sparse-Vektoren aus Rohtext generiert. Das ist ein großer operativer Vorteil. Ich muss BM25 nicht clientseitig berechnen, keine zusätzlichen Indizierungspipelines pflegen und keine Metadaten über mehrere Systeme hinweg synchronisieren. Alles—von Dense Embeddings über BM25 bis hin zum hybriden Ranking—befindet sich in einer einzigen Datenbank, wodurch der gesamte Retrieval-Workflow einfach, schnell und leicht zu warten bleibt.
AWS Bedrock (Titan Embeddings v2): Das Embedding-Modell
Für Dense-Vektor-Embeddings verwende ich Titan Embeddings v2 von AWS Bedrock. Es funktioniert gut über mehrere Sprachen hinweg und verarbeitet japanischen Text zuverlässig, was wichtig ist, wenn Sie gemischte Inhalte wie kurze Suchanfragen, lange Richtliniendokumente, Produktbeschreibungen und FAQ-artige Texte einbetten.
Reciprocal Rank Fusion (RRF): Die Reranking-Methode
Hybride Suche funktioniert nur, wenn Sie die Ergebnisse von Dense- und Sparse-Suche sinnvoll kombinieren können, und die beiden Score-Räume sind grundlegend unterschiedlich. RRF (Reciprocal Rank Fusion) löst dies sauber, indem Ergebnisse auf Grundlage ihres Rangs statt roher Scores zusammengeführt werden. Es erzeugt stabile, leicht nachvollziehbare hybride Ergebnisse ohne manuell abgestimmte Gewichtungen oder Normalisierungstricks.
Einsteigerfreundliches Tutorial zur hybriden Suche
Nachdem die Architektur geklärt ist, kommen wir zu etwas, das Sie tatsächlich ausführen können. Ich habe ein GitHub repo mit dem gesamten Code und den Beispieldaten zusammengestellt, die Sie benötigen, sodass das Setup bewusst leichtgewichtig ist. Sobald Sie einen kostenlosen Zilliz Cloud cluster starten und Ihren AWS Bedrock API key hinzufügen, können Sie drei Retrieval-Modi nebeneinander testen:
Dense-Vektorsuche
Sparse (BM25)-Volltextsuche
Hybride Suche (RRF-Fusion)
Der gesamte Workflow läuft mit geringen Kosten—nur die Bedrock-Embedding-Aufrufe verursachen Gebühren.
Schritt 1: Repository von GitHub klonen
Klonen Sie zuerst das Repository:
git clone [https://github.com/Beginnersguide138/rag-with-sudachi.git](https://github.com/Beginnersguide138/rag-with-sudachi.git)
Wechseln Sie in das Projektverzeichnis und richten Sie die Python-Umgebung ein:
cd rag-with-sudachi
uv sync # Install Python dependencies using uv
cp .env.example .env # Create an environment file based on the template
Schritt 2: Zilliz Cloud einrichten (Free Tier)
Zilliz Cloud läuft auf allen großen Cloud-Anbietern—AWS, GCP und Azure. Sie können sich direkt auf der Zilliz website registrieren oder über die jeweiligen Cloud-Marktplätze abonnieren. In diesem Tutorial verwende ich den Weg über den AWS Marketplace, da er eine schnelle Möglichkeit bietet, einen vollständig verwalteten Milvus-Cluster zu starten, ohne Infrastruktur anfassen zu müssen.
- Gehen Sie zum Zilliz Cloud-Eintrag im AWS Marketplace und klicken Sie auf „Try for free.“ Dadurch wird ein kostenloser serverloser Milvus-Cluster erstellt:
Es wird niemals automatisch in einen kostenpflichtigen Plan umgewandelt
Hat einige Einschränkungen (z. B. eingeschränkte Monitoring-Funktionen)
Der Cluster ist für dieses Tutorial zur hybriden Suche mehr als ausreichend
2. Öffne die Zilliz Cloud-Konsole nach Abschluss des Abonnements:
Erstelle eine neue Organization (nur ein logischer Container für deine Projekte).
Du siehst einen kostenlosen serverless Cluster, der bereits bereitgestellt wurde.
Kopiere den Cluster Endpoint und den API Key—du benötigst diese, wenn du dich aus deinem Code heraus verbindest.
Schritt 3: Umgebungsvariablen konfigurieren
Füge deine Zilliz- und Bedrock-Zugangsdaten in die .env-Datei ein:
# 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
Code-Hinweis: Kurzfristige Bedrock-Tokens laufen alle 12 Stunden ab. Das ist beabsichtigt—sie reduzieren den möglichen Schaden bei einer Offenlegung von Zugangsdaten und sind ideal für die lokale Entwicklung.
Schritt 4: Das Notebook starten oder das Skript ausführen
Öffne das Repository in VS Code. Das Haupt-Tutorial befindet sich in:
notebooks/hybrid_search_with_bm25.ipynb
Wenn du statt Jupyter Notebook einen reinen Python-Workflow bevorzugst, kannst du Folgendes ausführen:
python run_hybrid_search.py
Beide Versionen:
Erstellen das Milvus-Schema
Wenden Sudachi-Normalisierung an
Fügen dichte und sparse Vektoren ein
Vergleichen die Ergebnisse von semantischer, keywordbasierter und hybrider Suche
Technische Details
1. Der Schlüssel zur Verarbeitung von Japanisch: Textnormalisierung mit Sudachi
In Retrieval-Systemen für japanische Inhalte hängt ein großer Teil der Genauigkeit davon ab, wie Text während der Indexierung vorverarbeitet wird. Aus PDFs extrahierter Text enthält häufig uneinheitliche Abstände, orthografische Varianten oder Störzeichen, was oft zu verpassten Treffern und geringerem Recall führt.
Um dieses Problem zu lösen, verwendet diese Implementierung die Sudachi-Normalisierungsfunktion. Dieser Prozess standardisiert Tokens vor der Indexierung, sodass das Suchsystem unterschiedliche Schreibweisen und Darstellungen als gleichwertig behandeln kann.
Code: Sudachi-Normalisierungs-Wrapper
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()
Warum Normalisierung wichtig ist
Die Verwendung von normalized_form() vereinheitlicht Varianten wie:
Katakana: 「サーバー」 ⇔ 「サーバ」
Numerische Notation: 「第1条」 ⇔ 「第一条」
PDF-Abstandsrauschen: 「第 一 条」(unnatürliche Leerzeichen) ⇔ 「第一条」
Ohne Normalisierung führen diese Varianten zu:
Verpassten BM25-Treffern
Falscher sparse Vektor-Tokenisierung
Geringerem Recall für rechtlich strukturierte Abfragen
Durch die Normalisierung sowohl von Dokumenten als auch von Abfragen erhöht das hybride System die Trefferwahrscheinlichkeit erheblich.
2. Schemadesign in Zilliz Cloud (verwaltetes Milvus)
Milvus, der Kern von Zilliz Cloud, bietet eine Function-Funktion (verfügbar ab v2.4), die automatisch BM25-basierte sparse Vektoren in der Datenbank generiert. Dadurch entfällt die Notwendigkeit, BM25-Vektoren clientseitig vorzuberechnen.
Schemadefinition
# 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)
Dieses Design macht es überflüssig, Sparse-Vektoren bei der Dateneinfügung explizit zu übergeben, wodurch die betriebliche Komplexität erheblich reduziert wird.
Durch die Verlagerung der BM25-Vektorgenerierung in Milvus selbst:
Wird die Ingestion-Pipeline einfacher
Ist keine explizite Sparse-Vektor-Berechnung erforderlich
Vermeiden Sie die Pflege zusätzlichen Vorverarbeitungscodes
Wird die Skalierung wesentlich einfacher
Dies reduziert den betrieblichen Aufwand erheblich.
Indexdesign und Optimierungsstrategie
# 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"},
)
Dense-Vector-Index: HNSW
HNSW (Hierarchical Navigable Small World) ist ein graphbasierter ANN-Algorithmus, der in Vektordatenbanken weit verbreitet ist. Er bietet:
Hochgeschwindigkeits-Retrieval
Hohe Recall-Rate
Starke Leistung bei großer Skalierung
COSINE wird als Ähnlichkeitsmetrik verwendet, da Titan Embeddings in einem normalisierten Kosinusraum arbeiten.
Sparse-Vector-Index: Inverted Index mit MaxScore-Optimierung
Sparse-Vektoren verwenden eine traditionelle Inverted-Index-Struktur. Die zusätzliche DAAT_MAXSCORE-Optimierung bietet:
Document-at-a-time-Verarbeitung für effizientes Traversieren
Frühes Pruning von Dokumenten, die keine Top-k-Scores erreichen können
Reduzierte Berechnung ohne Beeinträchtigung der Genauigkeit
Dies führt zu einer deutlich schnelleren BM25-Suche.
3. Implementierung der hybriden Suche mit RRF
Um Ergebnisse aus Dense- (semantischen) und Sparse- (Keyword-)Suchen fair zusammenzuführen, verwendet das System Reciprocal Rank Fusion (RRF). RRF ist robust, einfach anzuwenden und erfordert weder Tuning noch Normalisierung über verschiedene Score-Typen hinweg.
Code für die hybride Suche
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\]
Vergleich der tatsächlichen Suchergebnisse
Das Tutorial bewertet Ergebnisse anhand öffentlich verfügbarer Dokumente der japanischen Finanzdienstleistungsbehörde. Das Notebook ermöglicht einen direkten Vergleich von:
Semantischer Suche (Dense Vector)
Volltextsuche (Sparse Vector)
Hybrider Suche (Dense + Sparse via RRF)
Fallstudie: Keyword-lastige Abfrage
Abfrage: “指定ADR機関が存在しない場合の苦情処理措置”
Hinweis: Die Abfrage bedeutet „Ein Verfahren zur Beschwerdebearbeitung, wenn keine benannte ADR-Organisation existiert.“
Ergebnisse:
Dense-Vector-Suche: Liefert häufig konzeptionell verwandte Passagen, hat jedoch Schwierigkeiten, exakte regulatorische Klauseln sichtbar zu machen.
Sparse-BM25-Suche: Identifiziert korrekt Dokumente, die Begriffe wie „benannte ADR-Organisation“ und „Maßnahmen zur Beschwerdebearbeitung“ enthalten, und stuft sie am höchsten ein.
Hybride Suche: Kombiniert die präzise Matching-Fähigkeit von BM25 mit zusätzlichem relevantem Kontext, der durch Dense Search abgerufen wird.
Dies zeigt, dass eine reine Dense-Suche das Risiko birgt, kritische Ergebnisse zu übersehen, wenn Nutzer mit spezialisierter Terminologie suchen. Hybride Suche ist für das Retrieval von Geschäftsdokumenten unerlässlich.
Zusammenfassung und Anwendungen
In diesem Artikel haben wir ein praktisches Hybrid-Search-Setup vorgestellt, das Sudachi-basierte Normalisierung mit Zilliz Cloud (managed Milvus) kombiniert. Das Ziel war einfach: eine Retrieval-Pipeline aufzubauen, die bei japanischem Text gut funktioniert, bei dem sowohl semantische Ähnlichkeit als auch exaktes Matching wichtig sind. Durch die Kombination von Dense Vectors, BM25 Sparse Vectors und RRF-basierter Fusion bleibt das System genau, einfach zu betreiben und an reale Produktions-Workloads anpassbar.
Zentrale Vorteile
Robust gegenüber Schreibvarianten: Sudachis Normalisierung glättet orthografische Unterschiede, Abstandsprobleme und Rauschen aus der PDF-Extraktion und verhindert so häufige Recall-Fehler in der japanischen Textsuche.
Geringer betrieblicher Aufwand: Milvus Functions übernehmen die BM25-Sparse-Vector-Erzeugung innerhalb der Datenbank. Keine zusätzlichen Preprocessing-Jobs, kein externer Suchdienst und keine duplizierte Indexierungslogik.
Hohe Gesamtgenauigkeit: RRF kombiniert Dense- und Sparse-Retrieval ohne komplexes Weight Tuning. Sie erhalten stabile hybride Ergebnisse, die sowohl konzeptionelle Abfragen als auch exakte Identifikatoren zuverlässig verarbeiten.
Mögliche Anwendungsfälle
Dieser hybride Ansatz eignet sich besonders für Szenarien, in denen Nutzer zwischen präzisen, strukturierten Abfragen und offener Sprache wechseln können:
Suche in internen Richtlinien und Handbüchern: Unterstützt exakte Referenzen (z. B. Artikelnummern) und verarbeitet zugleich vage oder explorative Abfragen.
E-Commerce-Produktsuche: Ermöglicht die präzise Suche nach Teilenummern und bietet gleichzeitig ähnlichkeitsbasierte Empfehlungen.
Wissensdatenbanken im Kundensupport: Gleicht strukturierte Begriffe wie Fehlercodes ab und interpretiert dennoch natürliche Nutzereingaben („画面が真っ黒です“, „ログインできない“).
Der vollständige Quellcode und das in diesem Artikel verwendete Jupyter Notebook sind im folgenden Repository verfügbar: GitHub: rag-with-sudachi
Die Kosten, um alles auszuprobieren, sind minimal – nur die AWS Bedrock Embedding-Aufrufe werden berechnet. Die kostenlose serverlose Stufe von Zilliz Cloud reicht aus, um den gesamten Workflow auszuführen.
Wenn Sie hybride Suche für Produktionssysteme oder interne Prototypen evaluieren, ist dieses Beispiel ein ausgezeichneter Ausgangspunkt.
Weiterlesen

Introducing Zilliz CLI and Agent Skills for Zilliz Cloud
Manage your vector database from your terminal or AI coding agent. Zilliz CLI and Agent Skills work with Claude Code, Cursor, Codex, and Copilot.

Announcing the General Availability of Single Sign-On (SSO) on Zilliz Cloud
SSO is GA on Zilliz Cloud, delivering the enterprise-grade identity management capabilities your teams need to deploy vectorDB with confidence.

What is the K-Nearest Neighbors (KNN) Algorithm in Machine Learning?
KNN is a supervised machine learning technique and algorithm for classification and regression. This post is the ultimate guide to KNN.



