针对多模态检索业务场景,PAI提供了端到端的多模态检索解决方案。该解决方案提供了图像、人脸、文本、文图和图文检索等服务,支持您通过调用EAS服务实现注册多模态数据、提取相关特征、基于ID管理多模态数据以及基于特征的多模态数据搜索等功能。本文为您介绍该解决方案的使用流程。
背景信息
功能支持
多模态特征提取能力:您可以使用基于Alibaba PAI EasyCV或EasyNLP提供的预训练模型,或通过DSW平台训练获得的图像特征提取模型、文本向量化模型以及文图CLIP模型部署服务。
特征检索能力:该服务默认使用基于DocArray-PAI和AliyunOSS的可持久化、可快速检索的特征数据库能力,支持您存储相关特征到AliyunOSS或从AliyunOSS拉起特征。例如:该服务中存储了10万特征,保存数据库并关闭服务以及初始化服务时,不需要再注册特征数据,即可搜索特征。您也可以配置其他检索产品,例如AliyunElasticSearch。
服务概览
目前,多模态检索解决方案支持部署的服务类型为:图像检索(image_retrieval)、人脸检索(faceid_retrieval),文本检索(text_retrieval)、中文多模态检索(imagetext_retrieval_cn)和英文多模态检索(imagetext_retrieval_en)。
各服务提供的调用接口为:服务初始化接口(init、set_root_path等)、数据库管理层接口(add、delete等)和数据库层接口(db_set、db_get等)。
使用流程
多模态检索解决方案的使用流程如下。
使用PAI提供的预训练模型,或在DSW平台参考Gallery示例自行构建模型。
通过模型在线服务EAS,您可以将训练好的模型或PAI提供的预训练模型部署为在线服务。
通过API方式调用服务初始化接口、数据库管理层接口和数据库层接口,实现多模态数据检索。
前提条件
在开始执行操作前,请确认您已完成以下准备工作:
已开通PAI(DSW、EAS)后付费,并创建默认工作空间,详情请参见创建工作空间。
已创建OSS存储空间(Bucket),用于存储数据集、训练获得的模型文件和配置文件。关于如何创建存储空间,详情请参见控制台创建存储空间。
已创建DSW实例,且运行正常,详情请参见创建DSW实例。建议:
镜像选择Pytorch1.8,例如
pytorch-develop:1.8pai-gpu-py36-cu101-ubuntu18.04
。资源规格使用GPU机型P100或V100,且内存大于等于32 GB,例如ecs.gn6v-c8g1.2xlarge。
构建模型
您可以使用PAI提供的预训练模型,具体如下表所示。
模型类型 | Processor种类 | Predictor | 模型路径 |
image_retrieval (图像检索) | EasyCV | easycv.predictors.feature_extractor.TorchFeatureExtractor | |
faceid_retrieval (人脸检索) | EasyCV | easycv.predictors.feature_extractor.TorchFaceFeatureExtractor | |
imagetext_retrieval_cn (中文CLIP) | EasyNLP | easynlp.appzoo.CLIPPredictor | |
imagetext_retrieval_en (英文CLIP) | EasyNLP | easynlp.appzoo.CLIPPredictor | |
text_retrieval (文本向量化模型) | EasyNLP | easynlp.appzoo.FeatureVectorizationPredictor |
您也可以在DSW平台参考Gallery示例自行构建模型,具体操作步骤如下。
进入DSW Gallery页面,详情请参见DSW Gallery。
在DSW Gallery页面,构建以下两种模型。
多模态检索模型
在名称或描述文本框中输入CLIP,然后按回车键。在右侧的基于EasyNLP的多模态CLIP图文检索区域,单击在DSW中打开。单击后即会自动将本教程所需的资源和教程文件下载至DSW实例中,并在下载完成后自动打开教程文件。
在打开的教程文件easynlp_clip.ipynb文件中,您可以直接运行对应的步骤的命令,当成功运行结束一个步骤命令后,再顺次运行下个步骤的命令。
图像检索模型
在名称或描述文本框中输入Swin Transformer,然后按回车键。在右侧的基于SwinTransformer的图像分类示例区域,单击在DSW中打开。单击后即会自动将本教程所需的资源和教程文件下载至DSW实例中,并在下载完成后自动打开教程文件。
在打开的教程文件easycv_classification_Swin.ipynb文件中,您可以直接运行对应的步骤的命令,当成功运行结束一个步骤命令后,再顺次运行下个步骤的命令。
部署模型服务
通过模型在线服务EAS,您可以将训练好的模型部署为在线服务,具体操作步骤如下。
进入模型在线服务(EAS)页面。
登录PAI控制台。
在左侧导航栏单击工作空间列表,在工作空间列表页面中单击待操作的工作空间名称,进入对应的工作空间。
在工作空间页面的左侧导航栏选择 ,进入模型在线服务(EAS)页面。
部署模型服务。
在模型在线服务(EAS)页面,单击部署服务,然后在自定义模型部署区域,单击JSON独立部署。
在JSON独立部署页面的编辑框中,配置以下内容。
{ "cloud": { "computing": { "instance_type": "ecs.gn6i-c16g1.4xlarge" } }, "containers": [ { "image": "eas-registry-vpc.<region>.cr.aliyuncs.com/pai-eas/diffuser-inference:easyretrieval1.1.0-pytorch1.8.1-gpu-py309-cu111-ubuntu22.04", "port": 8000, "script": "python /ml/code/app.py --model_type imagetext_retrieval_cn" } ], "features": { "eas.aliyun.com/extra-ephemeral-storage": "100Gi" }, "metadata": { "cpu": 16, "gpu": 1, "instance": 1, "memory": 62000, "name": "<your_service_name>" }, "storage": [ { "mount_path": "/mnt/models", "oss": { "path": "oss://pai-quickstart-{region}/easycv/models/easyretrieval/", "readOnly": true }, "properties": { "resource_type": "model" } } ] }
其中关键参数配置说明如下,其他参数使用JSON文件中的配置,更多参数配置说明,请参见服务模型所有相关参数说明。
参数
描述
metadata
name
请配置您自己的服务名称,同地域内唯一。
containers
image
请将<region>替换为服务所在地域ID,例如华东2(上海)为cn-shanghai。关于如何查询地域ID,请参见地域和可用区。
storage
oss.path
本方案使用PAI提供的公开预置模型路径,您只需将<region>替换为服务所在地域ID,例如华东2(上海)为cn-shanghai。关于如何查询地域ID,请参见地域和可用区。
您也可以使用上述步骤提供的预置模型和DSW平台训练得到的模型。
cloud
computing.instance_type
实例规格,必须为GPU类型。
单击部署。当服务状态为运行中时,表明服务部署成功。
查看服务访问地址和Token。
在模型在线服务(EAS)页面,单击目标服务的服务方式列下的调用信息。
在调用信息对话框的公网地址调用页签,获取服务访问地址和Token。
调用模型服务
服务调用方式
完整的POST调用代码如下。
import requests,json
head = {
"Authorization":"xxxxxx" # head为部署服务后,PAI-EAS返回的服务调用密钥Token对应的字符串。
}
our_oss_io_config = dict(ak_id='xxxxxx',
ak_secret='xxxxxx',
hosts='oss-*****-internal.aliyuncs.com',
buckets=['examplebucket'])
datas = json.dumps({
"function_name": "XXX" # 必选,调用接口的名称。
"function_params": {
param1: XXX # 参考不同接口对应的参数说明。
param2:
....
},
})
hosts = "xxxxxx/test"
r = requests.post(hosts, data=datas, headers=head)
其中关键参数配置如下所示。
参数 | 描述 |
Authorization | 配置为上述步骤已查询的服务Token。 |
our_oss_io_config.ak_id | 阿里云账号的AccessKey ID。 |
our_oss_io_config.ak_secret | 阿里云账号的AccessKey Secret。 |
our_oss_io_config.hosts | 您OSS地域的Endpoint。OSS地域与Endpoint的对应关系,请参见访问域名和数据中心。 重要 需要配置为对应地域的内网Endpoint,否则访问不通。 |
our_oss_io_config.buckets | 您创建的OSS存储空间(Bucket)的名称,与服务所在地域一致。 |
function_name | 接口名称,支持以下取值:
|
function_params | 参数配置,详情请参见function_name对应的接口说明。 |
hosts | 配置为上述步骤已查询的服务公网访问地址。 |
接口使用示例如下:
服务初始化接口-set_root_path
POST代码示例
datas = json.dumps({ "function_name" :"set_root_path", "function_params" : { "root_path": "oss://examplebucket/ljh-xiaoling/da_test/", }, })
POST返回示例(请求成功)
{ "request_id": "b576c16e-7fe2-46d4-9502-35771*******", "success": True, "info": "None", }
数据库管理层接口-save
POST代码示例
datas = json.dumps({ "function_name" : "save", "function_params" : {}, })
POST返回示例(请求成功)
{ "request_id": "f355c3d9-d235-41dd-b262-695966******", "success": True, "save": "Done", }
数据库接口-db_search
POST代码示例
datas = json.dumps({ "function_name": "db_search", "function_params": { "database_name": "test_1", "uri": "oss://examplebucket/ljh-xxxx/da_test/000001.jpeg", "search_topk": 2, "metric" : "cosine" }, })
POST返回示例(请求成功)
{ "request_id": "70c2d344-adf9-4b07-b888-cabce0******", "success": True, "db_search": [[{'scores': 0.4860914349555969, 'uri': 'oss://examplebucket/ljh-xiaoling/data/image/000015.jpg', 'text': '', 'group_id': '0', 'intra_id': 0}]] }
服务调用示例
多模态图像检索服务首先需要建立多模态图像检索数据库,然后将注册到数据库中的多模态数据及图像进行特征提取,最后从多模态图像数据库的数据中,对上传的多模态数据及图像进行相似快速检索。整个过程需要使用的接口包括数据库初始化、增加数据库、增加数据及检索数据等接口。下文提供一个简单的示例供您参考。
分别创建以下Python脚本。
数据库初始化脚本retrieval_init.py:
import requests import json head = { "Authorization": "xxxxxx" # head为部署服务后,EAS返回的服务调用密钥Token对应的字符串。 } our_oss_io_config = dict(ak_id='xxxxxx', # 阿里云账号的AccessKey。 ak_secret='xxxxxx', # 阿里云账号的AccessKey Secret。 hosts='oss-cn-****-internal.aliyuncs.com', # 内网Endpoint。 buckets=['examplebucket']) # OSS Bucket。 datas = json.dumps({ "function_name": "init", "function_params": { "backend": "oss", "root_path": "oss://examplebucket/xxx", "oss_io_config": our_oss_io_config, }, }) hosts = 'http://16640818xxxxxx.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/img_retrieval_001' r = requests.post(hosts, data=datas, headers=head) print(r.content) print("test ending")
其中examplebucket替换为OSS存储空间(Bucket)名称,与服务所在地域一致。其他参数配置说明,请参见服务调用方式。
增加数据库脚本retrieval_add.py:
import requests import json ENCODING = 'utf-8' datas = json.dumps({ 'function_name': 'add', 'function_params': { 'database_name': 'test_1', }, }) hosts = 'http://16640818xxxxxx.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/img_retrieval_001' head = { "Authorization": "NTE3Y2M2ZmEzZGQ3ZGRkOGM4ZDE1MDxxxxxxxxxxxxxx" } r = requests.post(hosts, data=datas, headers=head) print(r.content) print("test ending")
其中hosts和Authorization需要配置为上述步骤已获取的服务访问地址和Token。
指定Predictor脚本retrieval_set_predictor.py:
import requests import json ENCODING = 'utf-8' datas = json.dumps({ "function_name": "set_predictor", "function_params": { 'preprocess': 'load_uri_to_base64str', }, }) hosts = 'http://16640818xxxxxx.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/img_retrieval_001' head = { "Authorization": "NTE3Y2M2ZmEzZGQ3ZGRkOGM4ZDE1MDxxxxxxxxxxxxxx" } r = requests.post(hosts, data=datas, headers=head) # r = requests.post("http://0.0.0.0:8000/test", data=datas, timeout=1500) print(r.content) print("test ending")
其中hosts和Authorization需要配置为上述步骤已获取的服务访问地址和Token。
增加数据的脚本retrieval_db_set.py:
import requests import json ENCODING = 'utf-8' datas = json.dumps({ 'function_name': 'db_set', 'function_params': { 'database_name': 'test_1', 'uri': [ 'oss://examplebucket/ljh-xxxx/data/image/000015.jpg', ], 'group_id': ['0'], # 存入该数据的群组名。 'embedding_attr': 'uri' }, }) hosts = 'http://16640818xxxxxx.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/img_retrieval_001' head = { "Authorization": "NTE3Y2M2ZmEzZGQ3ZGRkOGM4ZDE1MDxxxxxxxxxxxxxx" } r = requests.post(hosts, data=datas, headers=head) print(r.content) print("test ending")
其中hosts和Authorization需要配置为上述步骤已获取的服务访问地址和Token;url配置为图片的OSS路径。
检索数据的脚本retrieval_db_search.py:
import requests import json ENCODING = 'utf-8' datas = json.dumps({ 'function_name': 'db_search', 'function_params': { 'database_name': 'test_1', 'uri': 'oss://examplebucket/ljh-xxxx/da_test/000001.jpeg', 'search_topk': 1, # 返回的最相似的k个数据 'metric': 'cosine' }, }) hosts = 'http://16640818xxxxxx.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/img_retrieval_001' head = { "Authorization": "NTE3Y2M2ZmEzZGQ3ZGRkOGM4ZDE1MDxxxxxxxxxxxxxx" } r = requests.post(hosts, data=datas, headers=head) print(r.content) print("test ending")
其中hosts和Authorization需要配置为上述步骤已获取的服务访问地址和Token;url配置为图片的OSS路径。
在终端中,分别在脚本文件所在目录依次执行数据库初始化脚本、增加数据库脚本、指定Predictor脚本以及增加数据的脚本。
python <retrieval_xxx.py>
其中<retrieval_xxx.py>需要替换为实际的Python脚本名称。
针对部署好的数据库,执行检索数据的脚本进行目标图像检索。
python retrieval_db_search.py
得到的推理预测结果如下所示。
{"request_id": "d4b4c7c5-2330-49d5-8ffb-a15e490b****", "success": true, "info": [[{"scores": 0.0, "uri": "oss://examplebucket/xxx/000001.jpeg", "text": "", "group_id": "0", "intra_id": 0}]]}
从上述模型推理的返回结果可以看出,模型服务返回了该数据库中与目标图像相似度最高的图片的URL。