Visión general del analizador
En el tratamiento de textos, un analizador es un componente crucial que convierte el texto en bruto en un formato estructurado que permite realizar búsquedas. Cada analizador suele constar de dos elementos básicos: un tokenizador y un filtro. Juntos, transforman el texto de entrada en tokens, los refinan y los preparan para una indexación y recuperación eficaces.
Desarrollados por Tantivy, los analizadores en Milvus se configuran durante la creación de la colección cuando se añaden campos VARCHAR
al esquema de la colección. Los tokens producidos por un analizador pueden utilizarse para crear un índice para la correspondencia de texto o convertirse en incrustaciones dispersas para la búsqueda de texto completo. Para obtener más información, consulte Coincidencia de texto o Búsqueda de texto completo.
El uso de analizadores puede afectar al rendimiento.
Búsqueda de texto completo: Para la búsqueda de texto completo, los canales DataNode y QueryNode consumen datos más lentamente porque deben esperar a que se complete la tokenización. Como resultado, los datos recién ingresados tardan más en estar disponibles para la búsqueda.
Coincidencia de texto: Para la coincidencia de texto, la creación de índices también es más lenta, ya que la tokenización debe finalizar antes de que se pueda crear un índice.
Anatomía de un analizador
Un analizador en Milvus consiste exactamente en un tokenizador y cero o más filtros.
Tokenizador: El tokenizador divide el texto de entrada en unidades discretas llamadas tokens. Estos tokens pueden ser palabras o frases, dependiendo del tipo de tokenizador.
Filtros: Se pueden aplicar filtros a los tokens para refinarlos aún más, por ejemplo, poniéndolos en minúsculas o eliminando palabras comunes.
El siguiente flujo de trabajo muestra cómo procesa el texto un analizador.
Tipos de analizadores
Milvus proporciona dos tipos de analizadores para satisfacer diferentes necesidades de procesamiento de texto.
Analizador incorporado: Se trata de configuraciones predefinidas que cubren tareas comunes de procesamiento de texto con una configuración mínima. Los analizadores integrados son ideales para búsquedas generales, ya que no requieren una configuración compleja.
Analizador personalizado: Para requisitos más avanzados, los analizadores personalizados le permiten definir su propia configuración especificando tanto el tokenizador como cero o más filtros. Este nivel de personalización es especialmente útil para casos de uso especializados en los que se necesita un control preciso sobre el procesamiento del texto.
Si omite las configuraciones del analizador durante la creación de la colección, Milvus utiliza por defecto el analizador standard
para todo el procesamiento de texto. Para más detalles, consulte Estándar.
Analizador incorporado
Los analizadores incorporados en Milvus están preconfigurados con tokenizadores y filtros específicos, lo que le permite utilizarlos inmediatamente sin necesidad de definir estos componentes usted mismo. Cada analizador incorporado sirve como plantilla que incluye un tokenizador y filtros preestablecidos, con parámetros opcionales para su personalización.
Por ejemplo, para utilizar el analizador incorporado standard
, basta con especificar su nombre standard
como type
y, opcionalmente, incluir configuraciones adicionales específicas para este tipo de analizador, como 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"]
}'
La configuración del analizador incorporado standard
anterior es equivalente a configurar un analizador personalizado con los siguientes parámetros, donde las opciones tokenizer
y filter
se definen explícitamente para lograr la misma funcionalidad:
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 ofrece los siguientes analizadores integrados, cada uno de los cuales puede utilizarse directamente especificando su nombre como parámetro type
.
standard
: Adecuado para el procesamiento de texto de uso general, aplicando la tokenización estándar y el filtrado de minúsculas.english
: Optimizado para texto en inglés, con soporte para palabras vacías en inglés.chinese
: Especializado para el tratamiento de texto chino, con tokenización adaptada a las estructuras del idioma chino.
Analizador personalizado
Para un procesamiento de texto más avanzado, los analizadores personalizados de Milvus le permiten construir una cadena de procesamiento de texto a medida especificando tanto un tokenizador como filtros. Esta configuración es ideal para casos de uso especializado en los que se requiere un control preciso.
Tokenizador
El tokenizador es un componente obligatorio para un analizador personalizado, que inicia el proceso de análisis descomponiendo el texto de entrada en unidades discretas o tokens. La tokenización sigue reglas específicas, como la división por espacios en blanco o signos de puntuación, dependiendo del tipo de tokenizador. Este proceso permite un tratamiento más preciso e independiente de cada palabra o frase.
Por ejemplo, un tokenizador convertiría el texto "Vector Database Built for Scale"
en tokens separados.
["Vector", "Database", "Built", "for", "Scale"]
Ejemplo de especificación de un tokenizador.
analyzer_params = {
"tokenizer": "whitespace",
}
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", "whitespace");
const analyzer_params = {
"tokenizer": "whitespace",
};
export analyzerParams='{
"type": "whitespace"
}'
Filtro
Los filtros son componentes opcionales que trabajan sobre los tokens producidos por el tokenizador, transformándolos o refinándolos según sea necesario. Por ejemplo, tras aplicar un filtro lowercase
a los términos tokenizados ["Vector", "Database", "Built", "for", "Scale"]
, el resultado podría ser.
["vector", "database", "built", "for", "scale"]
Los filtros de un analizador personalizado pueden ser integrados o personalizados, en función de las necesidades de configuración.
Filtros integrados: Preconfigurados por Milvus, requieren una configuración mínima. Puede utilizar estos filtros directamente especificando sus nombres. Los siguientes filtros están incorporados para su uso directo.
lowercase
: Convierte el texto a minúsculas, asegurando una coincidencia insensible a mayúsculas y minúsculas. Para más detalles, consulte Minúsculas.asciifolding
: Convierte los caracteres no ASCII en equivalentes ASCII, lo que simplifica el tratamiento de textos multilingües. Para más información, consulte Plegado ASCII.alphanumonly
: Conserva sólo los caracteres alfanuméricos eliminando los demás. Para más detalles, consulte Sólo alfanuméricos.cnalphanumonly
: Elimina los tokens que contienen caracteres que no sean chinos, letras inglesas o dígitos. Para obtener más información, consulte Cnalphanumonly.cncharonly
: Elimina los tokens que contienen caracteres no chinos. Para más información, consulte Cncharonly.
Ejemplo de uso de un filtro incorporado:
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"] }'
Filtros personalizados: Los filtros personalizados permiten configuraciones especializadas. Puede definir un filtro personalizado eligiendo un tipo de filtro válido (
filter.type
) y añadiendo configuraciones específicas para cada tipo de filtro. Ejemplos de tipos de filtro que admiten personalizaciónstop
: Elimina palabras comunes especificadas estableciendo una lista de palabras de detención (por ejemplo,"stop_words": ["of", "to"]
). Para obtener más información, consulte Detener.length
: Excluye los tokens en función de criterios de longitud, como el establecimiento de una longitud máxima de token. Para obtener más información, consulte Longitud.stemmer
: Reduce las palabras a su raíz para una búsqueda más flexible. Para más detalles, consulte Stemmer.
Ejemplo de configuración de un filtro personalizado:
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"] } ] }'
Ejemplo de uso
En este ejemplo, definimos un esquema de colección con un campo vectorial para incrustaciones y dos campos VARCHAR
para capacidades de procesamiento de texto. Cada campo VARCHAR
está configurado con sus propios ajustes de analizador para manejar diferentes necesidades de procesamiento.
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
}"