机器学习推理搜索请求处理器
搜索ml_inference请求处理器用于调用已注册的机器学习 (ML) 模型,以便使用模型输出重写查询。
前提条件:
在使用ml_inference搜索请求处理器之前,您必须拥有托管在 UDB-SX集群上的本地机器学习模型,或者通过 ML Commons 插件连接到 UDB-SX 集群的外部托管模型。有关本地模型的更多信息,请参阅“在 UDB-SX 中使用机器学习模型”。有关外部托管模型的更多信息,请参阅“连接到外部托管模型”。
语法
以下是ml-inference搜索请求处理器的语法:
{
"ml_inference": {
"model_id": "<model_id>",
"function_name": "<function_name>",
"full_response_path": "<full_response_path>",
"query_template": "<query_template>",
"model_config": {
"<model_config_field>": "<config_value>"
},
"model_input": "<model_input>",
"input_map": [
{
"<model_input_field>": "<query_input_field>"
}
],
"output_map": [
{
"<query_output_field>": "<model_output_field>"
}
]
}
}
配置参数
下表列出了ml-inference搜索请求处理器的必需参数和可选参数。
| 参数 | 数据类型 | 必填/选填 | 描述 |
|:–| :— |:—|:—|
| model_id| String | 必填 | 处理器使用的机器学习模型的ID。 |
| query_template | String | 选填 | 用于构建包含查询字符串的新查询的查询字符串模板new_document_field,通常在将搜索查询重写为新的查询类型时使用。 |
| function_name | String | 对于外部托管模型,此项为选填;
对于本地模型,此项为必填。 | 处理器中配置的机器学习模型的函数名称。对于本地模型,有效值为sparse_encoding`` <model_name>、<model_name> sparse_tokenize、 text_embedding<model_name> 和 <model_name> text_similarity。对于外部托管模型,有效值为 <model_name> remote。默认值为 <model_name> remote。|
| model_config | Object | 选填 | 机器学习模型的自定义配置选项。对于外部托管的模型,如果设置了此配置,则会覆盖默认连接器参数。对于本地模型,您可以添加此配置model_config以覆盖model_input注册期间设置的模型配置。有关更多信息,请参阅对象model_config。 |
| model_input | String |对于外部托管模型,此项为选填;
对于本地模型,此项为必填 | 定义模型所需输入字段格式的模板。每种本地模型类型可能使用不同的输入集。对于外部托管模型,默认值为 "{ \"parameters\": ${ml_inference.parameters} }. |
| input_map | Array | 必填 | 一个数组,指定如何将查询字符串字段映射到模型输入字段。数组中的每个元素都是格式中的映射,对应文档字段的一次模型调用。如果外部托管模型未指定输入映射,则所有文档字段直接作为输入传递给模型。大小表示模型被调用的次数(即预测API请求的次数)。"<model_input_field>": "<query_input_field>"input_map |
| <model_input_field> | String | 必填 | 模型输入字段名称。 |
| <query_input_field> | String | 必填 | 用作模型输入的查询字段的名称或 JSON 路径。 |
| output_map | Array | 格式 | 一个数组,用于指定如何将模型输出字段映射到查询字符串中的新字段。数组中的每个元素都是一个映射,格式如下 "<query_output_field>": "<model_output_field>". |
| <query_output_field> | String | 必填 | model_output存储模型输出(由指定)的查询字段的名称。 |
| <model_output_field> | String | 必填 | 要存储在模型输出中的字段的名称或 JSON 路径 query_output_field。 |
| full_response_path | Boolean | 选填 | 如果model_output_field中包含的是指向该字段的完整 JSON 路径(而非字段名称),则将此参数设置为true。这样,模型输出将被完全解析以获取该字段的值。对于本地模型,默认值为true,而对于外部托管模型,默认值为false。 |
| ignore_missing | Boolean | 选填 | 如果 true 且在 input_map 或 output_map 中定义的任何输入字段缺失,则忽略此处理器。否则,缺失字段会导致失败。默认值为 false。 |
| ignore_failure | Boolean | 选填 | 指定处理器在遇到错误时是否继续执行。如果为 true,则忽略此处理器并继续搜索。如果为 false,则任何失败都会导致搜索被取消。默认值为 false。 |
| max_prediction_tasks | Integer | 选填 | 在查询搜索过程中能够同时运行的模型调用的最大数量。默认值为10。 |
| description | String | 选填 | 处理器的简要描述。 |
| tag | String | 选填 | 处理器的标识标签。用于调试,以区分相同类型的处理器。 |
该
input_map映射output_map支持标准JSON 路径表示法,用于指定复杂的数据结构。
使用处理器
按照以下步骤来使用流水线中的处理器。在创建处理器时,您必须提供模型 ID、input_map和 output_map。在使用处理器测试流水线之前,请确保模型已成功部署。您可以使用获取模型 API 来检查模型状态。
对于本地模型,您必须提供一个model_input字段,该字段用于指定模型的输入格式。将model_config中的任何输入字段添加到model_input中。
对于外部托管的模型,model_input 字段是可选的,其默认值是"{ \"parameters\": ${ml_inference.parameters} }。
设置
创建一个名为index的索引my_index,并索引两个文档:
POST /my_index/_doc/1
{
"passage_text": "I am excited",
"passage_language": "en",
"label": "POSITIVE",
"passage_embedding": [
2.3886719,
0.032714844,
-0.22229004
...]
}
POST /my_index/_doc/2
{
"passage_text": "I am sad",
"passage_language": "en",
"label": "NEGATIVE",
"passage_embedding": [
1.7773438,
0.4309082,
1.8857422,
0.95996094,
...]
}
当您在未使用搜索管道的情况下对已创建的索引运行词项查询时,该查询会搜索包含查询中指定确切词项的文档。以下查询不会返回任何结果,因为查询文本与索引中的任何文档都不匹配:
GET /my_index/_search
{
"query": {
"term": {
"passage_text": {
"value": "happy moments",
"boost": 1
}
}
}
}
通过使用模型,搜索流程可以根据模型推断结果动态重写词值,从而增强或改变搜索结果。这意味着模型会接收来自搜索查询的初始输入,对其进行处理,然后更新查询词以反映模型推断结果,从而有可能提高搜索结果的相关性。
示例:外部托管模型
以下示例配置了一个ml_inference具有外部托管模型的处理器。
步骤 1:创建管道
本示例演示如何为外部托管的情感分析模型创建搜索管道,该模型会重写词查询值。该模型需要一个inputs字段,并在一个字段中生成结果label。由于function_name未指定,因此默认值为remote,表示外部托管模型。
查询词值会根据模型的输出进行重写。ml_inference搜索请求中的处理器需要一个input_map用于检索模型输入的查询字段值,以及一个output_map用于将模型输出赋值给查询字符串的函数。
在这个例子中,ml_inference搜索请求处理器用于处理以下词项查询:
{
"query": {
"term": {
"label": {
"value": "happy moments",
"boost": 1
}
}
}
}
以下请求会创建一个搜索管道,该管道会重写前面的词项查询:
PUT /_search/pipeline/ml_inference_pipeline
{
"description": "Generate passage_embedding for searched documents",
"processors": [
{
"ml_inference": {
"model_id": "<your model id>",
"input_map": [
{
"inputs": "query.term.label.value"
}
],
"output_map": [
{
"query.term.label.value": "label"
}
]
}
}
]
}
当向外部托管模型发出 Predict API 请求时,所有必要的字段和参数通常都包含在一个parameters对象中:
POST /_plugins/_ml/models/cleMb4kBJ1eYAeTMFFg4/_predict
{
"parameters": {
"inputs": [
{
...
}
]
}
}
因此,要使用外部托管的情感分析模型,请按以下格式发送 Predict API 请求:
POST /_plugins/_ml/models/cywgD5EB6KAJXDLxyDp1/_predict
{
"parameters": {
"inputs": "happy moments"
}
}
该模型处理输入文本,并根据输入文本的情感倾向生成预测结果。在本例中,情感倾向为正面:
{
"inference_results": [
{
"output": [
{
"name": "response",
"dataAsMap": {
"label": "POSITIVE",
"score": "0.948"
}
}
],
"status_code": 200
}
]
}
在为外部托管模型指定字段时input_map,可以直接引用该inputs字段,而无需提供其点路径parameters.inputs:
"input_map": [
{
"inputs": "query.term.label.value"
}
]
步骤 2:运行管道
创建搜索管道后,您可以使用该搜索管道运行相同的词项查询:
GET /my_index/_search?search_pipeline=my_pipeline_request_review
{
"query": {
"term": {
"label": {
"value": "happy moments",
"boost": 1
}
}
}
}
根据模型的输出结果,查询词的值会被重写。模型判断查询词的情感倾向为正面,因此重写的查询如下所示:
{
"query": {
"term": {
"label": {
"value": "POSITIVE",
"boost": 1
}
}
}
}
响应中包含一个文档,该文档的某个label字段具有以下值POSITIVE:
{
"took": 288,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.00009405752,
"hits": [
{
"_index": "my_index",
"_id": "3",
"_score": 0.00009405752,
"_source": {
"passage_text": "I am excited",
"passage_language": "en",
"label": "POSITIVE"
}
}
]
}
}
示例:本地模型
以下示例向您展示如何配置ml_inference具有本地模型的处理器,以将词项查询重写为 k-NN 查询。
步骤 1:创建管道
以下示例展示了如何为huggingface/sentence-transformers/all-distilroberta-v1本地模型创建搜索管道。该模型是一个预训练的句子转换器模型,托管在您的 UDB-SX 集群中。
如果使用 Predict API 调用模型,则请求如下所示:
POST /_plugins/_ml/_predict/text_embedding/cleMb4kBJ1eYAeTMFFg4
{
"text_docs": [
"today is sunny"
],
"return_number": true,
"target_response": [
"sentence_embedding"
]
}
使用此方案,model_input按如下方式指定:
"model_input": "{ \"text_docs\": ${input_map.text_docs}, \"return_number\": ${model_config.return_number}, \"target_response\": ${model_config.target_response} }"
在映射中input_map,将query.term.passage_embedding.value查询字段映射text_docs到模型期望的字段:
"input_map": [
{
"text_docs": "query.term.passage_embedding.value"
}
]
因为您将要转换为嵌入的字段指定为一个 JSON 路径,所以您需要将 full_response_path 设置为 true。然后会解析整个 JSON 文档,以获取输入字段。
"full_response_path": true
该字段中的文本query.term.passage_embedding.value将用于生成词嵌入:
{
"text_docs": "happy passage"
}
Predict API 请求返回以下响应:
{
"inference_results": [
{
"output": [
{
"name": "sentence_embedding",
"data_type": "FLOAT32",
"shape": [
768
],
"data": [
0.25517133,
-0.28009856,
0.48519906,
...
]
}
]
}
]
}
该模型在$.inference_results.*.output.*.data字段中生成嵌入向量。并将output_map该字段映射到查询模板中的查询字段:
"output_map": [
{
"modelPredictionOutcome": "$.inference_results.*.output.*.data"
}
]
要使用ml_inference本地模型配置搜索请求处理器,请function_name显式指定。在本例中,为function_name。text_embedding有关有效值的信息function_name,请参阅配置参数。
以下是ml_inference处理器与本地模型的最终配置:
PUT /_search/pipeline/ml_inference_pipeline_local
{
"description": "searchs reviews and generates embeddings",
"processors": [
{
"ml_inference": {
"function_name": "text_embedding",
"full_response_path": true,
"model_id": "<your model id>",
"model_config": {
"return_number": true,
"target_response": [
"sentence_embedding"
]
},
"model_input": "{ \"text_docs\": ${input_map.text_docs}, \"return_number\": ${model_config.return_number}, \"target_response\": ${model_config.target_response} }",
"query_template": """{
"size": 2,
"query": {
"knn": {
"passage_embedding": {
"vector": ${modelPredictionOutcome},
"k": 5
}
}
}
}""",
"input_map": [
{
"text_docs": "query.term.passage_embedding.value"
}
],
"output_map": [
{
"modelPredictionOutcome": "$.inference_results.*.output.*.data"
}
],
"ignore_missing": true,
"ignore_failure": true
}
}
]
}
步骤 2:运行管道
运行以下查询,并在请求中提供管道名称:
GET /my_index/_search?search_pipeline=ml_inference_pipeline_local
{
"query": {
"term": {
"passage_embedding": {
"value": "happy passage"
}
}
}
}
该响应证实处理器运行了 k-NN 查询,返回了得分更高的文档 1:
{
"took": 288,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.00009405752,
"hits": [
{
"_index": "my_index",
"_id": "1",
"_score": 0.00009405752,
"_source": {
"passage_text": "I am excited",
"passage_language": "en",
"label": "POSITIVE",
"passage_embedding": [
2.3886719,
0.032714844,
-0.22229004
...]
}
},
{
"_index": "my_index",
"_id": "2",
"_score": 0.00001405052,
"_source": {
"passage_text": "I am sad",
"passage_language": "en",
"label": "NEGATIVE",
"passage_embedding": [
1.7773438,
0.4309082,
1.8857422,
0.95996094,
...
]
}
}
]
}
}