🚀 Попробуйте Zilliz Cloud, полностью управляемый Milvus, бесплатно — ощутите 10-кратное увеличение производительности! Попробовать сейчас>

milvus-logo
LFAI
Главная
  • Руководство пользователя
  • Home
  • Docs
  • Руководство пользователя

  • Схема и поля данных

  • Анализатор

  • Обзор анализатора

Обзор анализаторов

В обработке текстов анализатор - это важнейший компонент, преобразующий необработанный текст в структурированный, пригодный для поиска формат. Каждый анализатор обычно состоит из двух основных элементов: токенизатора и фильтра. Вместе они преобразуют входной текст в лексемы, уточняют эти лексемы и готовят их к эффективному индексированию и поиску.

Анализаторы в Milvus, работающие на базе Tantivy, настраиваются во время создания коллекции, когда вы добавляете поля VARCHAR в схему коллекции. Токены, созданные анализатором, могут быть использованы для построения индекса для сопоставления с текстом или преобразованы в разреженные вкрапления для полнотекстового поиска. Дополнительные сведения см. в разделе "Текстовое соответствие или полнотекстовый поиск".

Использование анализаторов может повлиять на производительность.

  • Полнотекстовый поиск: При полнотекстовом поиске каналы DataNode и QueryNode потребляют данные медленнее, поскольку им приходится ждать завершения токенизации. В результате вновь поступившие данные становятся доступными для поиска дольше.

  • Текстовое соответствие: При сопоставлении текстов создание индекса также происходит медленнее, поскольку перед созданием индекса необходимо завершить токенизацию.

Анатомия анализатора

Анализатор в Milvus состоит ровно из одного токенизатора и нуля или более фильтров.

  • Токенизатор: Токенизатор разбивает входной текст на дискретные единицы, называемые лексемами. Эти лексемы могут быть словами или фразами, в зависимости от типа токенизатора.

  • Фильтры: Фильтры могут применяться к лексемам для их дальнейшего уточнения, например, для перевода их в нижний регистр или удаления общих слов.

Токенизаторы поддерживают только формат UTF-8. Поддержка других форматов будет добавлена в будущих релизах.

Приведенный ниже рабочий процесс показывает, как анализатор обрабатывает текст.

analyzer-overview

Типы анализаторов

Milvus предоставляет два типа анализаторов для удовлетворения различных потребностей в обработке текста.

  • Встроенный анализатор: Это предопределенные конфигурации, которые решают общие задачи обработки текста с минимальной настройкой. Встроенные анализаторы идеально подходят для поиска общего назначения, поскольку не требуют сложной настройки.

  • Пользовательский анализатор: Для более сложных задач пользовательские анализаторы позволяют задать собственную конфигурацию, указав как токенизатор, так и ноль или более фильтров. Такой уровень настройки особенно полезен в специализированных случаях, когда требуется точный контроль над обработкой текста.

Если вы не указываете конфигурацию анализатора при создании коллекции, Milvus по умолчанию использует анализатор standard для обработки всего текста. Подробнее см. в разделе Стандартный.

Встроенный анализатор

Встроенные анализаторы в Milvus предварительно сконфигурированы с определенными токенизаторами и фильтрами, что позволяет использовать их сразу, без необходимости определять эти компоненты самостоятельно. Каждый встроенный анализатор представляет собой шаблон, включающий в себя предустановленные токенизаторы и фильтры, с дополнительными параметрами для настройки.

Например, чтобы использовать встроенный анализатор standard, достаточно указать его имя standard в качестве type и опционально включить дополнительные конфигурации, специфичные для этого типа анализатора, например stop_words.

analyzer_params = {
    "type": "standard", # Uses the standard built-in analyzer
    "stop_words": ["a", "an", "for"] # Defines a list of common words (stop words) to exclude from tokenization
}

Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("type", "standard");
analyzerParams.put("stop_words", Arrays.asList("a", "an", "for"));
const analyzer_params = {
    "type": "standard", // Uses the standard built-in analyzer
    "stop_words": ["a", "an", "for"] // Defines a list of common words (stop words) to exclude from tokenization
};
export analyzerParams='{
       "type": "standard",
       "stop_words": ["a", "an", "for"]
    }'

Приведенная выше конфигурация встроенного анализатора standard эквивалентна настройке пользовательского анализатора со следующими параметрами, где опции tokenizer и filter явно определены для достижения той же функциональности:

analyzer_params = {
    "tokenizer": "standard",
    "filter": [
        "lowercase",
        {
            "type": "stop",
            "stop_words": ["a", "an", "for"]
        }
    ]
}

Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", "standard");
analyzerParams.put("filter",
        Arrays.asList("lowercase",
                new HashMap<String, Object>() {{
                    put("type", "stop");
                    put("stop_words", Arrays.asList("a", "an", "for"));
                }}));
const analyzer_params = {
    "tokenizer": "standard",
    "filter": [
        "lowercase",
        {
            "type": "stop",
            "stop_words": ["a", "an", "for"]
        }
    ]
};
export analyzerParams='{
       "type": "standard",
       "filter":  [
       "lowercase",
       {
            "type": "stop",
            "stop_words": ["a", "an", "for"]
       }
   ]
}'

Milvus предлагает следующие встроенные анализаторы, каждый из которых можно использовать напрямую, указав его имя в качестве параметра type.

  • standard: : Подходит для обработки текста общего назначения, применяя стандартную токенизацию и фильтрацию строчных букв.

  • english: : Оптимизирован для англоязычного текста, с поддержкой английских стоп-слов.

  • chinese: Специализирован для обработки китайского текста, включая токенизацию, адаптированную к структурам китайского языка.

Пользовательский анализатор

Для более сложной обработки текста пользовательские анализаторы в Milvus позволяют создать индивидуальный конвейер обработки текста, указав токенизатор и фильтры. Такая настройка идеально подходит для специализированных случаев, когда требуется точный контроль.

Токенизатор

Токенизатор - это обязательный компонент пользовательского анализатора, который запускает конвейер анализатора, разбивая входной текст на дискретные единицы или токены. В зависимости от типа токенизатора токенизация выполняется по определенным правилам, таким как разбиение на пробельные символы или знаки препинания. Этот процесс позволяет более точно и независимо обрабатывать каждое слово или фразу.

Например, токенизатор преобразует текст "Vector Database Built for Scale" в отдельные лексемы.

["Vector", "Database", "Built", "for", "Scale"]

Пример указания токенизатора.

analyzer_params = {
    "tokenizer": "whitespace",
}
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", "whitespace");
const analyzer_params = {
    "tokenizer": "whitespace",
};
export analyzerParams='{
       "type": "whitespace"
    }'

Фильтр

Фильтры - это необязательные компоненты, работающие с токенами, полученными токенизатором, преобразуя или уточняя их по мере необходимости. Например, после применения фильтра lowercase к токенизированным терминам ["Vector", "Database", "Built", "for", "Scale"], результат может быть следующим.

["vector", "database", "built", "for", "scale"]

Фильтры в пользовательском анализаторе могут быть как встроенными, так и пользовательскими, в зависимости от потребностей конфигурации.

  • Встроенные фильтры: Предварительно сконфигурированы Milvus и требуют минимальной настройки. Вы можете использовать эти фильтры из коробки, указав их имена. Приведенные ниже фильтры являются встроенными для прямого использования.

    • lowercase: Преобразует текст в нижний регистр, обеспечивая сопоставление без учета регистра. Подробнее см. в разделе Нижний регистр.

    • asciifolding: Преобразует не ASCII-символы в ASCII-эквиваленты, упрощая работу с многоязычным текстом. Подробнее см. в разделе Сложение ASCII.

    • alphanumonly: Сохраняет только алфавитно-цифровые символы, удаляя остальные. Подробнее см. в разделе "Только алфавитно-цифровые".

    • cnalphanumonly: Удаляет лексемы, содержащие любые символы, кроме китайских, английских букв или цифр. Подробнее см. в разделе Cnalphanumonly.

    • cncharonly: Удаляет маркеры, содержащие любые некитайские символы. Подробнее см. в разделе Cncharonly.

    Пример использования встроенного фильтра:

    analyzer_params = {
        "tokenizer": "standard", # Mandatory: Specifies tokenizer
        "filter": ["lowercase"], # Optional: Built-in filter that converts text to lowercase
    }
    
    Map<String, Object> analyzerParams = new HashMap<>();
    analyzerParams.put("tokenizer", "standard");
    analyzerParams.put("filter", Collections.singletonList("lowercase"));
    
    const analyzer_params = {
        "tokenizer": "standard", // Mandatory: Specifies tokenizer
        "filter": ["lowercase"], // Optional: Built-in filter that converts text to lowercase
    }
    
    export analyzerParams='{
       "type": "standard",
       "filter":  ["lowercase"]
    }'
    
  • Пользовательские фильтры: Пользовательские фильтры позволяют создавать специализированные конфигурации. Вы можете определить пользовательский фильтр, выбрав подходящий тип фильтра (filter.type) и добавив специальные настройки для каждого типа фильтра. Примеры типов фильтров, поддерживающих настройку.

    • stop: Удаляет указанные общие слова, задавая список стоп-слов (например, "stop_words": ["of", "to"]). Подробнее см. в разделе "Стоп-слова".

    • length: Исключает лексемы на основе критериев длины, например, задавая максимальную длину лексемы. Подробнее см. в разделе Длина.

    • stemmer: Сокращает слова до их корневых форм для более гибкого подбора. Подробнее см. в разделе Стеммер.

    Пример настройки пользовательского фильтра:

    analyzer_params = {
        "tokenizer": "standard", # Mandatory: Specifies tokenizer
        "filter": [
            {
                "type": "stop", # Specifies 'stop' as the filter type
                "stop_words": ["of", "to"], # Customizes stop words for this filter type
            }
        ]
    }
    
    
    Map<String, Object> analyzerParams = new HashMap<>();
    analyzerParams.put("tokenizer", "standard");
    analyzerParams.put("filter",
        Collections.singletonList(new HashMap<String, Object>() {{
            put("type", "stop");
            put("stop_words", Arrays.asList("a", "an", "for"));
        }}));
    
    const analyzer_params = {
        "tokenizer": "standard", // Mandatory: Specifies tokenizer
        "filter": [
            {
                "type": "stop", // Specifies 'stop' as the filter type
                "stop_words": ["of", "to"], // Customizes stop words for this filter type
            }
        ]
    };
    
    export analyzerParams='{
        "type": "standard",
        "filter":  [
        {
                "type": "stop",
                "stop_words": ["a", "an", "for"]
        }
        ]
    }'
    

Пример использования

В этом примере мы определяем схему коллекции с векторным полем для вкраплений и двумя полями VARCHAR для возможностей обработки текста. Каждое поле VARCHAR имеет собственные настройки анализатора для обработки различных данных.

from pymilvus import MilvusClient, DataType

# Set up a Milvus client
client = MilvusClient(
    uri="http://localhost:19530"
)

# Create schema
schema = client.create_schema(auto_id=True, enable_dynamic_field=False)

# Add fields to schema

# Use a built-in analyzer
analyzer_params_built_in = {
    "type": "english"
}

# Add VARCHAR field `title_en`
schema.add_field(
    field_name='title_en', 
    datatype=DataType.VARCHAR, 
    max_length=1000, 
    enable_analyzer=True,
    analyzer_params=analyzer_params_built_in,
    enable_match=True, 
)

# Configure a custom analyzer
analyzer_params_custom = {
    "tokenizer": "standard",
    "filter": [
        "lowercase", # Built-in filter
        {
            "type": "length", # Custom filter
            "max": 40
        },
        {
            "type": "stop", # Custom filter
            "stop_words": ["of", "to"]
        }
    ]
}

# Add VARCHAR field `title`
schema.add_field(
    field_name='title', 
    datatype=DataType.VARCHAR, 
    max_length=1000, 
    enable_analyzer=True,
    analyzer_params=analyzer_params_custom,
    enable_match=True, 
)

# Add vector field
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=3)
# Add primary field
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)

# Set up index params for vector field
index_params = client.prepare_index_params()
index_params.add_index(field_name="embedding", metric_type="COSINE", index_type="AUTOINDEX")

# Create collection with defined schema
client.create_collection(
    collection_name="YOUR_COLLECTION_NAME",
    schema=schema,
    index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;

// Set up a Milvus client
ConnectConfig config = ConnectConfig.builder()
        .uri("http://localhost:19530")
        .build();
MilvusClientV2 client = new MilvusClientV2(config);

// Create schema
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
        .enableDynamicField(false)
        .build();

// Add fields to schema
// Use a built-in analyzer
Map<String, Object> analyzerParamsBuiltin = new HashMap<>();
analyzerParamsBuiltin.put("type", "english");
// Add VARCHAR field `title_en`
schema.addField(AddFieldReq.builder()
        .fieldName("title_en")
        .dataType(DataType.VarChar)
        .maxLength(1000)
        .enableAnalyzer(true)
        .analyzerParams(analyzerParamsBuiltin)
        .enableMatch(true)
        .build());

// Configure a custom analyzer
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", "standard");
analyzerParams.put("filter",
        Arrays.asList("lowercase",
                new HashMap<String, Object>() {{
                    put("type", "length");
                    put("max", 40);
                }},
                new HashMap<String, Object>() {{
                    put("type", "stop");
                    put("stop_words", Arrays.asList("a", "an", "for"));
                }}
        )
);
schema.addField(AddFieldReq.builder()
        .fieldName("title")
        .dataType(DataType.VarChar)
        .maxLength(1000)
        .enableAnalyzer(true)
        .analyzerParams(analyzerParams)
        .enableMatch(true) // must enable this if you use TextMatch
        .build());

// Add vector field
schema.addField(AddFieldReq.builder()
        .fieldName("embedding")
        .dataType(DataType.FloatVector)
        .dimension(3)
        .build());
// Add primary field
schema.addField(AddFieldReq.builder()
        .fieldName("id")
        .dataType(DataType.Int64)
        .isPrimaryKey(true)
        .autoID(true)
        .build());

// Set up index params for vector field
List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
        .fieldName("embedding")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .metricType(IndexParam.MetricType.COSINE)
        .build());

// Create collection with defined schema
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
        .collectionName("YOUR_COLLECTION_NAME")
        .collectionSchema(schema)
        .indexParams(indexes)
        .build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";

// Set up a Milvus client
const client = new MilvusClient("http://localhost:19530");
// Use a built-in analyzer for VARCHAR field `title_en`
const analyzerParamsBuiltIn = {
  type: "english",
};

// Configure a custom analyzer for VARCHAR field `title`
const analyzerParamsCustom = {
  tokenizer: "standard",
  filter: [
    "lowercase",
    {
      type: "length",
      max: 40,
    },
    {
      type: "stop",
      stop_words: ["of", "to"],
    },
  ],
};

// Create schema
const schema = {
  auto_id: true,
  fields: [
    {
      name: "id",
      type: DataType.INT64,
      is_primary: true,
    },
    {
      name: "title_en",
      data_type: DataType.VARCHAR,
      max_length: 1000,
      enable_analyzer: true,
      analyzer_params: analyzerParamsBuiltIn,
      enable_match: true,
    },
    {
      name: "title",
      data_type: DataType.VARCHAR,
      max_length: 1000,
      enable_analyzer: true,
      analyzer_params: analyzerParamsCustom,
      enable_match: true,
    },
    {
      name: "embedding",
      data_type: DataType.FLOAT_VECTOR,
      dim: 4,
    },
  ],
};

// Set up index params for vector field
const indexParams = [
  {
    name: "embedding",
    metric_type: "COSINE",
    index_type: "AUTOINDEX",
  },
];

// Create collection with defined schema
await client.createCollection({
  collection_name: "YOUR_COLLECTION_NAME",
  schema: schema,
  index_params: indexParams,
});

console.log("Collection created successfully!");

export schema='{
        "autoId": true,
        "enabledDynamicField": false,
        "fields": [
            {
                "fieldName": "id",
                "dataType": "Int64",
                "isPrimary": true
            },
            {
                "fieldName": "title_en",
                "dataType": "VarChar",
                "elementTypeParams": {
                    "max_length": 1000,
                    "enable_analyzer": true,
                    "enable_match": true,
                    "analyzer_params": {"type": "english"}
                }
            },
            {
                "fieldName": "title",
                "dataType": "VarChar",
                "elementTypeParams": {
                    "max_length": 1000,
                    "enable_analyzer": true,
                    "enable_match": true,
                    "analyzer_params": {
                        "tokenizer": "standard",
                        "filter":[
                            "lowercase",
                            {
                                "type":"length",
                                "max":40
                            },
                            {
                                "type":"stop",
                                "stop_words":["of","to"]
                            }
                        ]
                    }
                }
            },
            {
                "fieldName": "embedding",
                "dataType": "FloatVector",
                "elementTypeParams": {
                    "dim":3
                }
            }
        ]
    }'
    
export indexParams='[
        {
            "fieldName": "embedding",
            "metricType": "COSINE",
            "indexType": "AUTOINDEX"
        }
    ]'

export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
    \"collectionName\": \"YOUR_COLLECTION_NAME\",
    \"schema\": $schema,
    \"indexParams\": $indexParams
}"

Попробуйте Managed Milvus бесплатно

Zilliz Cloud работает без проблем, поддерживается Milvus и в 10 раз быстрее.

Начать
Обратная связь

Была ли эта страница полезной?