Lindera
Der Tokenizer lindera führt eine wörterbuchbasierte morphologische Analyse durch. Er wurde für Japanisch und Koreanisch entwickelt, wo Wörter nicht durch Leerzeichen getrennt werden und grammatikalische Marker (Partikel) direkt an Wörter angehängt werden.
Für chinesischen Text: Obwohl lindera Chinesisch über das Wörterbuch cc-cedict unterstützt, empfehlen wir die Verwendung des jieba Tokenizer zu verwenden. Jieba ist speziell für die Segmentierung chinesischer Wörter konzipiert und liefert bessere Ergebnisse.
Übersicht
Japanisch und Koreanisch sind agglutinierende Sprachen: Grammatikalische Marker, Partikel genannt, werden direkt an Substantive angehängt und bilden zahlreiche Kombinationen. Zum Beispiel:
Sprache |
Wortstamm |
+ Partikel |
= Kombinierte Form |
Bedeutung |
|---|---|---|---|---|
Koreanisch |
서울 (Seoul) |
에서 |
서울에서 |
in Seoul |
Japanisch |
東京 (Tokio) |
に |
東京に |
nach Tokio |
Der lindera Tokenizer:
Zerlegt den Text in einzelne Morpheme (Wörter und Partikel)
Markiert jedes Token mit Part-of-Speech (POS)-Informationen aus dem Wörterbuch
Anwendung von Filtern zur Entfernung unerwünschter Token (z. B. Partikel, Interpunktion)
Dieser zweistufige Prozess - Segmentierung gefolgt von POS-basierter Filterung - ermöglicht eine genaue Kontrolle darüber, welche Token für die Suche indiziert werden.
Voraussetzungen
Benutzer von Milvus 2.6+: Sie können diesen Abschnitt überspringen. Alle Wörterbücher sind vorkompiliert und in der offiziellen Version enthalten.
Für Milvus 2.5.x müssen Sie Milvus mit bestimmten Wörterbüchern kompilieren. Alle Wörterbücher müssen während der Kompilierung explizit eingebunden werden.
Um bestimmte Wörterbücher zu aktivieren, fügen Sie sie in den Kompilierungsbefehl ein:
make milvus TANTIVY_FEATURES=lindera-ipadic,lindera-ko-dic
Die vollständige Liste der verfügbaren Wörterbücher:
Wörterbuch |
Sprache |
Beschreibung |
|---|---|---|
lindera-ko-dic |
Koreanisch |
Koreanisches morphologisches Wörterbuch(MeCab Ko-dic) |
lindera-ipadisch |
Japanisch |
Morphologisches Standardwörterbuch(MeCab IPADIC) |
lindera-ipadic-neologd |
Japanisch |
Erweitertes Wörterbuch mit neuen Wörtern und Eigennamen(IPADIC NEologd) |
lindera-unidisch |
Japanisch |
Akademisches Standardwörterbuch(UniDic) |
lindera-cc-cedict |
Chinesisch |
Von der Gemeinschaft gepflegtes chinesisch-englisches Wörterbuch(CC-CEDICT) |
Zum Beispiel, um alle Wörterbücher zu aktivieren:
make milvus TANTIVY_FEATURES=lindera-ipadic,lindera-ipadic-neologd,lindera-unidic,lindera-ko-dic,lindera-cc-cedict
Konfiguration
Um einen Analyzer zu konfigurieren, der den lindera Tokenizer verwendet, setzen Sie tokenizer.type auf lindera, wählen Sie ein Wörterbuch mit dict_kind und wenden Sie optional Filter an.
analyzer_params = {
"tokenizer": {
"type": "lindera",
"dict_kind": "ko-dic",
"filter": [
{
"kind": "korean_stop_tags",
"tags": ["SP", "SSC", "SSO", "SC", "SE", "SF", "JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ", "JX", "JC", "UNK", "EP", "ETM"]
}
]
}
}
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", new HashMap<String, Object>() {{
put("type", "lindera");
put("dict_kind", "ko-dic");
put("filter", Arrays.asList(
new HashMap<String, Object>() {{
put("kind", "korean_stop_tags");
put("tags", Arrays.asList(
"SP", "SSC", "SSO", "SC", "SE", "SF",
"JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ",
"JX", "JC", "UNK", "EP", "ETM"
));
}}
));
}});
analyzerParams := map[string]interface{}{
"tokenizer": map[string]interface{}{
"type": "lindera",
"dict_kind": "ko-dic",
"filter": []interface{}{
map[string]interface{}{
"kind": "korean_stop_tags",
"tags": []string{
"SP", "SSC", "SSO", "SC", "SE", "SF",
"JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ",
"JX", "JC", "UNK", "EP", "ETM",
},
},
},
},
}
const analyzer_params = {
"tokenizer": {
"type": "lindera",
"dict_kind": "ko-dic",
"filter": [
{
"kind": "korean_stop_tags",
"tags": ["SP", "SSC", "SSO", "SC", "SE", "SF", "JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ", "JX", "JC", "UNK", "EP", "ETM"]
}
]
}
};
# restful
Parameter |
Beschreibung |
|---|---|
|
Der Typ des Tokenizers. Dieser ist auf |
|
Ein Wörterbuch, das zur Definition des Vokabulars verwendet wird. Mögliche Werte:
|
|
Eine Liste von Filtern auf Tokenizer-Ebene, die nach der Segmentierung anzuwenden sind. Jeder Filter ist ein Objekt mit:
|
Nachdem Sie analyzer_params definiert haben, können Sie sie bei der Definition eines Sammelschemas auf ein VARCHAR Feld anwenden. Dadurch kann Milvus den Text in diesem Feld unter Verwendung des angegebenen Analysators für eine effiziente Tokenisierung und Filterung verarbeiten. Details finden Sie unter Beispielanwendung.
Beispiele
Bevor Sie die Analyzer-Konfiguration auf Ihr Sammelschema anwenden, überprüfen Sie das Verhalten mit der Methode run_analyzer.
Koreanisches Beispiel
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
analyzer_params = {
"tokenizer": {
"type": "lindera",
"dict_kind": "ko-dic",
"filter": [
{
"kind": "korean_stop_tags",
"tags": ["SP", "SSC", "SSO", "SC", "SE", "SF", "JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ", "JX", "JC", "UNK", "EP", "ETM"]
}
]
}
}
# Sample Korean text: "서울에서 맛있는 음식을 먹었습니다" (I ate delicious food in Seoul)
sample_text = "서울에서 맛있는 음식을 먹었습니다"
result = client.run_analyzer(sample_text, analyzer_params)
print("Analyzer output:", result)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.RunAnalyzerReq;
import io.milvus.v2.service.vector.response.RunAnalyzerResp;
ConnectConfig config = ConnectConfig.builder()
.uri("http://localhost:19530")
.build();
MilvusClientV2 client = new MilvusClientV2(config);
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", new HashMap<String, Object>() {{
put("type", "lindera");
put("dict_kind", "ko-dic");
put("filter", Arrays.asList(
new HashMap<String, Object>() {{
put("kind", "korean_stop_tags");
put("tags", Arrays.asList(
"SP", "SSC", "SSO", "SC", "SE", "SF",
"JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ",
"JX", "JC", "UNK", "EP", "ETM"
));
}}
));
}});
List<String> texts = new ArrayList<>();
texts.add("서울에서 맛있는 음식을 먹었습니다");
RunAnalyzerResp resp = client.runAnalyzer(RunAnalyzerReq.builder()
.texts(texts)
.analyzerParams(analyzerParams)
.build());
List<RunAnalyzerResp.AnalyzerResult> results = resp.getResults();
import (
"context"
"encoding/json"
"fmt"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "localhost:19530",
APIKey: "root:Milvus",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
analyzerParams := map[string]interface{}{
"tokenizer": map[string]interface{}{
"type": "lindera",
"dict_kind": "ko-dic",
"filter": []interface{}{
map[string]interface{}{
"kind": "korean_stop_tags",
"tags": []string{
"SP", "SSC", "SSO", "SC", "SE", "SF",
"JKS", "JKC", "JKG", "JKO", "JKB", "JKV", "JKQ",
"JX", "JC", "UNK", "EP", "ETM",
},
},
},
},
}
bs, _ := json.Marshal(analyzerParams)
texts := []string{"서울에서 맛있는 음식을 먹었습니다"}
option := milvusclient.NewRunAnalyzerOption(texts).
WithAnalyzerParams(string(bs))
result, err := client.RunAnalyzer(ctx, option)
if err != nil {
fmt.Println(err.Error())
// handle error
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
uri: "http://localhost:19530",
});
const analyzer_params = {
tokenizer: {
type: "lindera",
dict_kind: "ko-dic",
filter: [
{
kind: "korean_stop_tags",
tags: [
"SP",
"SSC",
"SSO",
"SC",
"SE",
"SF",
"JKS",
"JKC",
"JKG",
"JKO",
"JKB",
"JKV",
"JKQ",
"JX",
"JC",
"UNK",
"EP",
"ETM",
],
},
],
},
};
const sample_text = "서울에서 맛있는 음식을 먹었습니다";
const result = await client.run_analyzer(sample_text, analyzer_params);
console.log("Analyzer output:", result);
# restful
Erwartete Ausgabe:
['서울', '맛있', '음식', '먹', '습니다']
Ohne korean_stop_tags würde die Ausgabe Partikel wie 에서 (in), 는 (Themenmarkierung) und 을 (Objektmarkierung) enthalten, die normalerweise für die Suche nicht nützlich sind.
Japanisches Beispiel
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
analyzer_params = {
"tokenizer": {
"type": "lindera",
"dict_kind": "ipadic",
"filter": [
{
"kind": "japanese_stop_tags",
"tags": ["接続詞", "助詞,格助詞", "助詞,格助詞,一般", "助詞,格助詞,引用", "助詞,格助詞,連語", "助詞,係助詞", "助詞,終助詞", "助詞,接続助詞", "助詞,特殊", "助詞,副助詞", "助詞,副助詞/並立助詞/終助詞", "助詞,連体化", "助詞,副詞化", "助詞,並立助詞", "助動詞", "記号,一般", "記号,読点", "記号,句点", "記号,空白", "記号,括弧閉", "記号,括弧開", "その他,間投", "フィラー", "非言語音"]
}
]
}
}
# Sample Japanese text: "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です"
sample_text = "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です"
result = client.run_analyzer(sample_text, analyzer_params)
print("Analyzer output:", result)
// java
// go
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
uri: "http://localhost:19530",
});
const analyzer_params = {
"tokenizer": {
"type": "lindera",
"dict_kind": "ipadic",
"filter": [
{
"kind": "japanese_stop_tags",
"tags": ["接続詞", "助詞,格助詞", "助詞,格助詞,一般", "助詞,格助詞,引用", "助詞,格助詞,連語", "助詞,係助詞", "助詞,終助詞", "助詞,接続助詞", "助詞,特殊", "助詞,副助詞", "助詞,副助詞/並立助詞/終助詞", "助詞,連体化", "助詞,副詞化", "助詞,並立助詞", "助動詞", "記号,一般", "記号,読点", "記号,句点", "記号,空白", "記号,括弧閉", "記号,括弧開", "その他,間投", "フィラー", "非言語音"]
}
]
}
}
// Sample Japanese text: "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です"
const sample_text = "東京スカイツリーの最寄り駅はとうきょうスカイツリー駅です"
const result = await client.run_analyzer(sample_text, analyzer_params);
console.log("Analyzer output:", result);
# restful
Erwartete Ausgabe:
['東京', 'スカイ', 'ツリー', '最寄り駅', 'とう', 'きょう', 'スカイ', 'ツリー', '駅']
Ohne japanese_stop_tags würde die Ausgabe Partikel wie の (Possessiv), は (Themenmarkierung) und です (Kopula) enthalten.