Lindera

Il tokenizer lindera esegue un'analisi morfologica basata su dizionari. È stato progettato per le lingue giapponese e coreana, dove le parole non sono separate da spazi e i marcatori grammaticali (particelle) sono collegati direttamente alle parole.

Per il testo cinese: Anche se lindera supporta il cinese tramite il dizionario cc-cedict, si consiglia di usare il jieba tokenizer. Jieba è stato progettato specificamente per la segmentazione delle parole cinesi e fornisce risultati migliori.

Panoramica

Il giapponese e il coreano sono lingue agglutinanti: i marcatori grammaticali chiamati particelle si attaccano direttamente ai sostantivi, formando numerose combinazioni. Ad esempio:

Lingua

Parola radice

+ Particella

= Forma combinata

Significato

Coreano

서울 (Seoul)

에서

서울에서

a Seoul

Giapponese

東京 (Tokyo)

東京に

a Tokyo

Il tokenizer lindera:

  1. Segmenta il testo in singoli morfemi (parole e particelle).

  2. Etichetta ogni token con informazioni POS (part-of-speech) dal dizionario

  3. Applica filtri per rimuovere i token indesiderati (ad esempio, particelle, punteggiatura).

Questo processo in due fasi, la segmentazione seguita dal filtraggio basato sul POS, consente di controllare con precisione quali token vengono indicizzati per la ricerca.

Prerequisiti

Utenti di Milvus 2.6+: È possibile saltare questa sezione. Tutti i dizionari sono precompilati e inclusi nella versione ufficiale.

Per Milvus 2.5.x, è necessario compilare Milvus con dizionari specifici abilitati. Tutti i dizionari devono essere inclusi esplicitamente durante la compilazione.

Per abilitare dizionari specifici, includerli nel comando di compilazione:

make milvus TANTIVY_FEATURES=lindera-ipadic,lindera-ko-dic

L'elenco completo dei dizionari disponibili:

Dizionario

Lingua

Descrizione

lindera-ko-dic

Coreano

Dizionario morfologico coreano(MeCab Ko-dic)

lindera-ipadico

Giapponese

Dizionario morfologico standard(MeCab IPADIC)

lindera-ipadico-neologo

Giapponese

Dizionario esteso con nuove parole e nomi propri(IPADIC NEologd)

lindera-unidic

Giapponese

Dizionario accademico standard(UniDic)

lindera-cc-cedict

Cinese

Dizionario cinese-inglese mantenuto dalla comunità(CC-CEDICT)

Ad esempio, per abilitare tutti i dizionari:

make milvus TANTIVY_FEATURES=lindera-ipadic,lindera-ipadic-neologd,lindera-unidic,lindera-ko-dic,lindera-cc-cedict

Configurazione

Per configurare un analizzatore che utilizza il tokenizer lindera, impostare tokenizer.type su lindera, scegliere un dizionario con dict_kind e applicare dei filtri opzionali.

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

Parametro

Descrizione

type

Il tipo di tokenizer. È fissato a "lindera".

dict_kind

Un dizionario usato per definire il vocabolario. Valori possibili:

  • ko-dic: Coreano - Dizionario morfologico coreano(MeCab Ko-dic)

  • ipadic: Giapponese - Dizionario morfologico standard(MeCab IPADIC)

  • ipadic-neologd: Giapponese con dizionario dei neologismi (esteso) - Include nuove parole e nomi propri(IPADIC NEologd)

  • unidic: Giapponese UniDic (esteso) - Dizionario accademico standard con informazioni linguistiche dettagliate(UniDic)

  • cc-cedict: Cinese mandarino (tradizionale/semplificato) - Dizionario cinese-inglese mantenuto dalla comunità(CC-CEDICT)

filter

Un elenco di filtri a livello di tokenizer da applicare dopo la segmentazione. Ogni filtro è un oggetto con:

  • kind: Il tipo di filtro. Valori supportati:

    • korean_stop_tags: Rimuove i token che corrispondono ai tag POS coreani specificati.

    • japanese_stop_tags: Rimuove i token corrispondenti ai tag POS giapponesi specificati.

  • tags: Un elenco di tag POS da filtrare. I tag disponibili dipendono da kind:

    • Per korean_stop_tags: Utilizzare codici di tag esatti (ad esempio, JKS, JKO, SF). I tag coreani richiedono una corrispondenza esatta. Per l'elenco completo basato sul tagset Sejong, vedere la fonte Lindera Korean stop tags.

    • Per japanese_stop_tags: Utilizzare i codici esatti dei tag (ad esempio, 助詞,格助詞, 助詞,係助詞, 助動詞). I tag giapponesi richiedono una corrispondenza esatta. Per l'elenco completo (IPADIC), vedere il riferimento ai tag POS giapponesi.

Dopo aver definito analyzer_params, è possibile applicarli a un campo VARCHAR quando si definisce uno schema di raccolta. Ciò consente a Milvus di elaborare il testo in quel campo utilizzando l'analizzatore specificato per una tokenizzazione e un filtraggio efficienti. Per i dettagli, si veda l'esempio di utilizzo.

Esempi

Prima di applicare la configurazione dell'analizzatore allo schema di raccolta, verificarne il comportamento con il metodo run_analyzer.

Esempio coreano

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

Risultato atteso:

['서울', '맛있', '음식', '먹', '습니다']

Senza korean_stop_tags, l'output includerebbe particelle come 에서 (in), (marcatore di argomento) e (marcatore di oggetto), che in genere non sono utili per la ricerca.

Esempio giapponese

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

Risultato atteso:

['東京', 'スカイ', 'ツリー', '最寄り駅', 'とう', 'きょう', 'スカイ', 'ツリー', '駅']

Senza japanese_stop_tags, l'output includerebbe particelle come (possessivo), (marcatore di argomento) e です (copula).

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

Questa pagina è stata utile?