分析器概述
在文字處理中,分析器是將原始文字轉換成結構化、可搜尋格式的重要元件。每個分析器通常包含兩個核心元件:標記器和過濾 器。它們共同將輸入文字轉換為標記,精煉這些標記,並為有效的索引和檢索做好準備。
Milvus 的分析器由Tantivy 提供,當您將VARCHAR
欄位新增至集合模式時,分析器會在集合建立時設定。分析器產生的標記可用於建立文字比對索引,或轉換成稀疏內嵌以進行全文檢索。如需詳細資訊,請參閱文字匹配或全文搜尋。
使用分析器可能會影響效能。
全文本搜尋:對於全文本搜尋,DataNode 和QueryNode通道消耗資料的速度較慢,因為它們必須等待標記化完成。因此,新擷取的資料需要較長時間才能可供搜尋。
文字匹配:對於文字匹配,索引建立的速度也較慢,因為標記化需要在建立索引之前完成。
分析器剖析
Milvus 的分析器包含一個標記器和零個或多個過濾器。
標記器:標記器將輸入文字分割成稱為標記的獨立單位。這些標記可以是單字或短語,取決於標記器類型。
篩選器:篩選器可應用於標記,以進一步精細它們,例如,使它們小寫或移除常用字。
標記器只支援 UTF-8 格式。其他格式的支援將在未來的版本中加入。
下面的工作流程顯示分析器如何處理文字。
分析器類型
Milvus 提供兩種類型的分析器,以滿足不同的文字處理需求。
內建分析器:這些是預先定義的配置,只需最少的設定即可涵蓋常見的文字處理工作。內建分析器不需要複雜的設定,是一般用途搜尋的理想選擇。
自訂分析器:對於更進階的需求,自訂分析器可讓您透過指定標記器和零個或多個過濾器來定義您自己的組態。這種層級的自訂對於需要精確控制文字處理的專門用例特別有用。
如果您在建立集合時省略了分析器設定,Milvus 預設會使用standard
分析器來處理所有文字。詳情請參閱標準。
內建分析器
Milvus 的內建分析器預先設定了特定的 tokenizer 和過濾器,讓您可以立即使用,而不需要自己定義這些元件。每個內建分析器都是一個範本,包含預設的標記器和篩選器,以及可選的自訂參數。
例如,若要使用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"]
指定 tokenizer 的範例。
analyzer_params = {
"tokenizer": "whitespace",
}
Map<String, Object> analyzerParams = new HashMap<>();
analyzerParams.put("tokenizer", "whitespace");
const analyzer_params = {
"tokenizer": "whitespace",
};
export analyzerParams='{
"type": "whitespace"
}'
過濾器
過濾器是可選的元件,用來處理 tokenizer 產生的 token,並視需要轉換或精煉它們。例如,將lowercase
過濾器套用到標記化的詞彙["Vector", "Database", "Built", "for", "Scale"]
之後,結果可能是。
["vector", "database", "built", "for", "scale"]
自訂分析器中的篩選器可以是內建或自訂的,視配置需求而定。
內建過濾器:由 Milvus 預先設定,只需最少的設定。您只要指定這些篩選器的名稱,就能立即使用這些篩選器。以下篩選器為內建篩選器,可直接使用。
lowercase
:將文字轉換為小寫,確保大小寫不敏感的匹配。如需詳細資訊,請參閱小寫。asciifolding
:將非 ASCII 字元轉換為 ASCII 對應字元,簡化多語言文字處理。詳情請參閱ASCII 折疊。alphanumonly
:只保留字母數字字符,移除其他字符。詳情請參閱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
:根據長度標準排除標記,例如設定最大標記長度。詳情請參閱Length。stemmer
:將字詞縮減為字根形式,以便進行更靈活的匹配。如需詳細資訊,請參閱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
}"