自定义本地模型
2.9 版本引入
要在本地使用自定义模型,您可以将其上传到 OpenSearch 集群。
模型支持
从 OpenSearch 2.6 开始,OpenSearch 支持本地文本嵌入模型。
从 OpenSearch 2.11 开始,OpenSearch 支持本地稀疏编码模型。
从 OpenSearch 2.12 开始,OpenSearch 支持本地交叉编码器模型。
从 OpenSearch 2.13 开始,OpenSearch 支持本地问答模型。
不支持在 CentOS 7 操作系统上运行本地模型。此外,并非所有本地模型都能在所有硬件和操作系统上运行。
准备模型
对于所有模型,您必须在模型 zip 文件中提供一个分词器 JSON 文件。
对于稀疏编码模型,请确保您的输出格式为 {"output":<sparse_vector>}
,以便 ML Commons 可以后处理稀疏向量。
如果您在自己的数据集上微调稀疏模型,您可能也希望使用自己的稀疏分词器模型。最好在分词器模型 zip 文件中提供您自己的 IDF JSON 文件,因为这会在您在查询中使用分词器模型时提高查询性能。或者,您可以使用 OpenSearch 提供的通用 来自 MSMARCO 的 IDF。如果未提供 IDF 文件,则每个 Token 的默认权重将设置为 1,这可能会影响稀疏神经搜索性能。
模型格式
要在 OpenSearch 中使用模型,您需要将模型导出为可移植格式。截至 2.5 版本,OpenSearch 仅支持 TorchScript 和 ONNX 格式。
在将模型文件上传到 OpenSearch 之前,您必须将其保存为 zip 格式。为确保 ML Commons 可以上传您的模型,请在上传之前压缩您的 TorchScript 文件。例如,下载一个 TorchScript 模型文件。
此外,您必须为模型 zip 文件计算 SHA256 校验和,这在注册模型时需要提供。例如,在 UNIX 上,使用以下命令获取校验和
shasum -a 256 sentence-transformers_paraphrase-mpnet-base-v2-1.0.0-onnx.zip
模型大小
大多数深度学习模型都超过 100 MB,这使得它们难以适应单个文档。OpenSearch 将模型文件分割成更小的块,存储在模型索引中。在为 OpenSearch 集群分配 ML 或数据节点时,请确保正确设置 ML 节点的大小,以便在进行 ML 推理时有足够的内存。
先决条件
要将自定义模型上传到 OpenSearch,您需要在 OpenSearch 集群外部准备它。您可以使用预训练模型(例如来自 Hugging Face 的模型),或者根据您的需求训练一个新模型。
集群设置
本示例使用一个简单的设置,没有专用的 ML 节点,并允许在非 ML 节点上运行模型。
在具有专用 ML 节点的集群上,指定 "only_run_on_ml_node": "true"
以提高性能。有关更多信息,请参阅 ML Commons 集群设置。
为确保此基本本地设置正常工作,请指定以下集群设置
PUT _cluster/settings
{
"persistent": {
"plugins.ml_commons.allow_registering_model_via_url": "true",
"plugins.ml_commons.only_run_on_ml_node": "false",
"plugins.ml_commons.model_access_control_enabled": "true",
"plugins.ml_commons.native_memory_threshold": "99"
}
}
步骤 1:注册模型组
要注册模型,您有以下选项
- 您可以使用
model_group_id
将模型版本注册到现有模型组。 - 如果您不使用
model_group_id
,ML Commons 将创建一个带有新模型组的模型。
要注册模型组,请发送以下请求:
POST /_plugins/_ml/model_groups/_register
{
"name": "local_model_group",
"description": "A model group for local models"
}
响应包含模型组 ID,您将使用它向此模型组注册模型。
{
"model_group_id": "wlcnb4kBJ1eYAeTMHlV6",
"status": "CREATED"
}
要了解有关模型组的更多信息,请参阅模型访问控制。
步骤 2:注册本地模型
要将本地模型注册到步骤 1 中创建的模型组,请发送 Register Model API 请求。有关 Register Model API 参数的说明,请参阅 注册模型。
function_name
对应于模型类型。对于文本嵌入模型,将此参数设置为 TEXT_EMBEDDING
。对于稀疏编码模型,将此参数设置为 SPARSE_ENCODING
或 SPARSE_TOKENIZE
。对于交叉编码器模型,将此参数设置为 TEXT_SIMILARITY
。对于问答模型,将此参数设置为 QUESTION_ANSWERING
。在本示例中,将 function_name
设置为 TEXT_EMBEDDING
,因为您正在注册一个文本嵌入模型。
提供步骤 1 中的模型组 ID 并发送以下请求
POST /_plugins/_ml/models/_register
{
"name": "huggingface/sentence-transformers/msmarco-distilbert-base-tas-b",
"version": "1.0.1",
"model_group_id": "wlcnb4kBJ1eYAeTMHlV6",
"description": "This is a port of the DistilBert TAS-B Model to sentence-transformers model: It maps sentences & paragraphs to a 768 dimensional dense vector space and is optimized for the task of semantic search.",
"function_name": "TEXT_EMBEDDING",
"model_format": "TORCH_SCRIPT",
"model_content_size_in_bytes": 266352827,
"model_content_hash_value": "acdc81b652b83121f914c5912ae27c0fca8fabf270e6f191ace6979a19830413",
"model_config": {
"model_type": "distilbert",
"embedding_dimension": 768,
"framework_type": "sentence_transformers",
"all_config": "{\"_name_or_path\":\"old_models/msmarco-distilbert-base-tas-b/0_Transformer\",\"activation\":\"gelu\",\"architectures\":[\"DistilBertModel\"],\"attention_dropout\":0.1,\"dim\":768,\"dropout\":0.1,\"hidden_dim\":3072,\"initializer_range\":0.02,\"max_position_embeddings\":512,\"model_type\":\"distilbert\",\"n_heads\":12,\"n_layers\":6,\"pad_token_id\":0,\"qa_dropout\":0.1,\"seq_classif_dropout\":0.2,\"sinusoidal_pos_embds\":false,\"tie_weights_\":true,\"transformers_version\":\"4.7.0\",\"vocab_size\":30522}"
},
"created_time": 1676073973126,
"url": "https://artifacts.opensearch.org/models/ml-models/huggingface/sentence-transformers/msmarco-distilbert-base-tas-b/1.0.1/torch_script/sentence-transformers_msmarco-distilbert-base-tas-b-1.0.1-torch_script.zip"
}
请注意,在 OpenSearch Dashboards 中,将 all_config
字段内容用三引号 ("""
) 包裹会自动转义字段内的引号并提供更好的可读性
POST /_plugins/_ml/models/_register
{
"name": "huggingface/sentence-transformers/msmarco-distilbert-base-tas-b",
"version": "1.0.1",
"model_group_id": "wlcnb4kBJ1eYAeTMHlV6",
"description": "This is a port of the DistilBert TAS-B Model to sentence-transformers model: It maps sentences & paragraphs to a 768 dimensional dense vector space and is optimized for the task of semantic search.",
"function_name": "TEXT_EMBEDDING",
"model_format": "TORCH_SCRIPT",
"model_content_size_in_bytes": 266352827,
"model_content_hash_value": "acdc81b652b83121f914c5912ae27c0fca8fabf270e6f191ace6979a19830413",
"model_config": {
"model_type": "distilbert",
"embedding_dimension": 768,
"framework_type": "sentence_transformers",
"all_config": """{"_name_or_path":"old_models/msmarco-distilbert-base-tas-b/0_Transformer","activation":"gelu","architectures":["DistilBertModel"],"attention_dropout":0.1,"dim":768,"dropout":0.1,"hidden_dim":3072,"initializer_range":0.02,"max_position_embeddings":512,"model_type":"distilbert","n_heads":12,"n_layers":6,"pad_token_id":0,"qa_dropout":0.1,"seq_classif_dropout":0.2,"sinusoidal_pos_embds":false,"tie_weights_":true,"transformers_version":"4.7.0","vocab_size":30522}"""
},
"created_time": 1676073973126,
"url": "https://artifacts.opensearch.org/models/ml-models/huggingface/sentence-transformers/msmarco-distilbert-base-tas-b/1.0.1/torch_script/sentence-transformers_msmarco-distilbert-base-tas-b-1.0.1-torch_script.zip"
}
OpenSearch 返回注册操作的任务 ID。
{
"task_id": "cVeMb4kBJ1eYAeTMFFgj",
"status": "CREATED"
}
要检查操作状态,请将任务 ID 提供给 获取任务
GET /_plugins/_ml/tasks/cVeMb4kBJ1eYAeTMFFgj
操作完成后,状态将变为 COMPLETED
。
{
"model_id": "cleMb4kBJ1eYAeTMFFg4",
"task_type": "REGISTER_MODEL",
"function_name": "TEXT_EMBEDDING",
"state": "COMPLETED",
"worker_node": [
"XPcXLV7RQoi5m8NI_jEOVQ"
],
"create_time": 1689793598499,
"last_update_time": 1689793598530,
"is_async": false
}
记下返回的 model_id
,因为部署模型时需要它。
步骤 3:部署模型
部署操作从模型索引中读取模型的块,然后创建模型实例并加载到内存中。模型越大,模型被分割的块就越多,加载到内存所需的时间也越长。
要部署已注册的模型,请在以下请求中提供其在步骤 3 中的模型 ID
POST /_plugins/_ml/models/cleMb4kBJ1eYAeTMFFg4/_deploy
响应中包含任务 ID,您可以使用它来检查部署操作的状态
{
"task_id": "vVePb4kBJ1eYAeTM7ljG",
"status": "CREATED"
}
与上一步一样,通过调用任务 API 检查操作状态
GET /_plugins/_ml/tasks/vVePb4kBJ1eYAeTM7ljG
操作完成后,状态将变为 COMPLETED
。
{
"model_id": "cleMb4kBJ1eYAeTMFFg4",
"task_type": "DEPLOY_MODEL",
"function_name": "TEXT_EMBEDDING",
"state": "COMPLETED",
"worker_node": [
"n-72khvBTBi3bnIIR8FTTw"
],
"create_time": 1689793851077,
"last_update_time": 1689793851101,
"is_async": true
}
如果集群或节点重启,则需要重新部署模型。要了解如何设置自动重新部署,请参阅启用自动重新部署。
步骤 4(可选):测试模型
使用 预测 API 来测试模型。
对于文本嵌入模型,发送以下请求
POST /_plugins/_ml/_predict/text_embedding/cleMb4kBJ1eYAeTMFFg4
{
"text_docs":[ "today is sunny"],
"return_number": true,
"target_response": ["sentence_embedding"]
}
响应包含所提供句子的文本嵌入
{
"inference_results" : [
{
"output" : [
{
"name" : "sentence_embedding",
"data_type" : "FLOAT32",
"shape" : [
768
],
"data" : [
0.25517133,
-0.28009856,
0.48519906,
...
]
}
]
}
]
}
对于稀疏编码模型,发送以下请求
POST /_plugins/_ml/_predict/sparse_encoding/cleMb4kBJ1eYAeTMFFg4
{
"text_docs":[ "today is sunny"]
}
响应包含 Token 和权重
{
"inference_results": [
{
"output": [
{
"name": "output",
"dataAsMap": {
"response": [
{
"saturday": 0.48336542,
"week": 0.1034762,
"mood": 0.09698499,
"sunshine": 0.5738209,
"bright": 0.1756877,
...
}
}
}
}
}
步骤 5:将模型用于搜索
要了解如何将模型用于向量搜索,请参阅 AI 搜索方法。
问答模型
问答模型从给定上下文中提取问题的答案。ML Commons 支持 text
格式的上下文。
要注册问答模型,请发送以下格式的请求。将 function_name
指定为 QUESTION_ANSWERING
POST /_plugins/_ml/models/_register
{
"name": "question_answering",
"version": "1.0.0",
"function_name": "QUESTION_ANSWERING",
"description": "test model",
"model_format": "TORCH_SCRIPT",
"model_group_id": "lN4AP40BKolAMNtR4KJ5",
"model_content_hash_value": "e837c8fc05fd58a6e2e8383b319257f9c3859dfb3edc89b26badfaf8a4405ff6",
"model_config": {
"model_type": "bert",
"framework_type": "huggingface_transformers"
},
"url": "https://github.com/opensearch-project/ml-commons/blob/main/ml-algorithms/src/test/resources/org/opensearch/ml/engine/algorithms/question_answering/question_answering_pt.zip?raw=true"
}
然后发送请求部署模型
POST _plugins/_ml/models/<model_id>/_deploy
要测试问答模型,请发送以下请求。它需要一个 question
和相关的 context
,答案将从其中生成。
POST /_plugins/_ml/_predict/question_answering/<model_id>
{
"question": "Where do I live?"
"context": "My name is John. I live in New York"
}
响应根据上下文提供答案
{
"inference_results": [
{
"output": [
{
"result": "New York"
}
}
}