분석기 개요
텍스트 처리에서 분석기는 원시 텍스트를 구조화되고 검색 가능한 형식으로 변환하는 중요한 구성 요소입니다. 각 분석기는 일반적으로 토큰화기와 필터라는 두 가지 핵심 요소로 구성됩니다. 이들은 함께 입력 텍스트를 토큰으로 변환하고, 이러한 토큰을 정제하며, 효율적인 색인 및 검색을 위해 준비합니다.
Tantivy에 의해 구동되는 Milvus의 분석기는 컬렉션 스키마에 VARCHAR
필드를 추가할 때 컬렉션 생성 중에 구성됩니다. 분석기가 생성한 토큰은 텍스트 매칭을 위한 인덱스를 구축하는 데 사용하거나 전체 텍스트 검색을 위해 스파스 임베딩으로 변환할 수 있습니다. 자세한 내용은 텍스트 일치 또는 전체 텍스트 검색을 참조하세요.
분석기를 사용하면 성능에 영향을 미칠 수 있습니다.
전체 텍스트 검색: 전체 텍스트 검색의 경우, 토큰화가 완료될 때까지 기다려야 하기 때문에 DataNode 및 QueryNode 채널은 데이터를 더 느리게 소비합니다. 따라서 새로 수집된 데이터를 검색에 사용할 수 있게 되는 데 시간이 더 오래 걸립니다.
텍스트 일치: 텍스트 매칭의 경우, 인덱스를 구축하기 전에 토큰화가 완료되어야 하므로 인덱스 생성도 더 느려집니다.
분석기의 구조
Milvus의 분석기는 정확히 하나의 토큰화기와 0개 이상의 필터로 구성됩니다.
토큰화 도구: 토큰화기는 입력 텍스트를 토큰이라는 개별 단위로 분해합니다. 이러한 토큰은 토큰라이저 유형에 따라 단어 또는 구문일 수 있습니다.
필터: 필터: 토큰에 필터를 적용하여 토큰을 소문자로 만들거나 일반적인 단어를 제거하는 등 토큰을 더욱 세분화할 수 있습니다.
아래 워크플로에서는 분석기가 텍스트를 처리하는 방법을 보여줍니다.
분석기 유형
Milvus는 서로 다른 텍스트 처리 요구 사항을 충족하기 위해 두 가지 유형의 분석기를 제공합니다.
내장 분석기: 최소한의 설정으로 일반적인 텍스트 처리 작업을 처리하는 사전 정의된 구성입니다. 기본 제공 분석기는 복잡한 구성이 필요하지 않으므로 범용 검색에 이상적입니다.
사용자 정의 분석기: 보다 고급 요구 사항이 필요한 경우, 사용자 정의 분석기를 사용하면 토큰화 도구와 0개 이상의 필터를 모두 지정하여 자신만의 구성을 정의할 수 있습니다. 이 수준의 사용자 지정은 텍스트 처리에 대한 정밀한 제어가 필요한 특수한 사용 사례에 특히 유용합니다.
수집 생성 중에 분석기 구성을 생략하는 경우, 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"
}'
필터
필터는 토큰화 도구가 생성한 토큰에 대해 필요에 따라 토큰을 변형하거나 정제하는 선택적 구성 요소입니다. 예를 들어, 토큰화된 용어 ["Vector", "Database", "Built", "for", "Scale"]
에 lowercase
필터를 적용하면 다음과 같은 결과가 나올 수 있습니다.
["vector", "database", "built", "for", "scale"]
사용자 정의 분석기의 필터는 구성 요구 사항에 따라 기본 제공 또는 사용자 정의가 가능합니다.
기본 제공 필터: Milvus에서 미리 구성한 것으로, 최소한의 설정만 필요합니다. 이러한 필터는 이름을 지정하여 바로 사용할 수 있습니다. 아래 필터는 바로 사용할 수 있는 기본 제공 필터입니다.
lowercase
: 텍스트를 소문자로 변환하여 대소문자를 구분하지 않는 매칭을 보장합니다. 자세한 내용은 소문자를 참조하세요.asciifolding
: ASCII가 아닌 문자를 ASCII에 해당하는 문자로 변환하여 다국어 텍스트 처리를 간소화합니다. 자세한 내용은 ASCII 접기를 참조하세요.alphanumonly
: 다른 문자를 제거하여 영숫자 문자만 유지합니다. 자세한 내용은 영숫자만을 참조하세요.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
}"