实验准备
1. 实验场景
本实验将阿里云Elasticsearch作为支持向量近邻搜索的向量查询引擎,结合在Elasticsearch实例部署开源模型,将查询文本的语义特征向量化的方式,将文本和图片映射到同一个向量空间,实现图片和文本的跨模态相似性比对检索,搭建基于向量检索的以文搜图的搜索服务原型,并使用阿里云Serverless 应用引擎 SAE实现了前端web应用demo。
说明:本实验由阿里云与Elastic公司合作创作,实验原始代码来源于flask-elastic-nlp项目,点击查看Github项目地址
2. 实验资源
本实验场景使用的实验资源和配置,说明如下。
说明:本示例遵循最小原则,使用满足场景需求的最小资源。
资源:检索分析服务 Elasticsearch 版、Serverless 应用引擎 SAE、传统型负载均衡 CLB
免费试用说明:
首购客户可以免费试用Serverless 应用引擎 SAE、传统型负载均衡 CLB可以使用免费试用资源。
付费说明:
本实验推荐使用阿里云 Elasticsearch 4C8G规格的按量付费资源,计费标准3.7元起/时(不同地域价格略有差异);如果用户没有SAE免费试用领取资格,推荐使用SAE 2C4G规格的按量付费资源,计费标准为单实例0.0074074元/min。
实验完毕您可以释放实例,整个实验耗时约1~2小时,整体消费预计5~30元,实际收费情况请参见您的费用账单。
网络连通要求:
因本实验所需的云产品之间的网络连通性要求,请注意,开通以下云产品资源时,所有组件须选择相同地域,如华北2(北京),并使用同一VPC同一可用区,保证组件之间的内网连通。
产品开通顺序:
首先开通检索分析服务Elasticsearch后付费实例、然后领取CLB免费试用、最后领取SAE免费试用,产品之间的配置有前后依赖关系。
云产品资源 |
规格 |
用途 |
阿里云检索分析服务 Elasticsearch 版 |
按量付费 通用商业版8.5版本 数据节点规格4C8G |
向量检索 |
Serverless 应用引擎 SAE |
首购用户可领取免费试用资源包 实例规格2C4G |
创建web应用 |
传统型负载均衡 CLB |
首购用户可领取免费试用资源包 |
web应用公网访问 |
3. 实验简介
通过对该实验的学习,我们实现:
- 创建并访问检索分析服务Elasticsearch版实例
- 使用快照恢复的方式将数据集和模型导入到Elasticsearch实例
- 通过Kibana完成Elasticsearch实例上的模型部署和测试
- 通过Serverless 应用引擎 SAE快速部署应用并上线
4. 体验目标
本项目将通过简易快速的阿里云相关组件和开源模型部署,通过1小时的动手实操,搭建基于Elasticsearch向量检索的以文搜图的搜索服务原型。
5. 背景知识(产品介绍)
本场景主要涉及以下云产品和服务:
阿里云Elasticsearch是基于开源Elasticsearch构建的全托管Elasticsearch云服务,在100%兼容开源功能的同时,支持开箱即用、按需付费。不仅提供云上开箱即用的Elasticsearch、Logstash、Kibana、Beats在内的Elastic Stack生态组件,还与Elastic官方合作提供免费X-Pack(白金版高级特性)商业插件,集成了安全、SQL、机器学习、告警、监控等高级特性,被广泛应用于实时日志分析处理、信息检索、以及数据的多维查询和统计分析等场景。
Serverless 应用引擎 SAE(Serverless App Engine)是一个全托管、免运维、高弹性的通用 PaaS 平台。SAE 支持 Spring Boot、Spring Cloud、Dubbo、HSF、Web 应用和 XXL-JOB、ElasticJob 任务的全托管,零改造迁移、无门槛容器化、并提供了开源侧诸多增强能力和企业级高级特性。
6. 前置知识
区别于传统的文本关键词搜索,现代的文本语义搜索、相似图片搜索、还有文本搜索图片的跨模态搜索普遍采用向量相似搜索的方式来实现。基本原理是将文本、图片通过深度学习模型映射到一个高纬度的向量空间,然后通过衡量向量的相似程度就可以找到最相关的文本或者图片。
下面就分5个方面详细讲解文本搜索图片、图片搜索图片应用所需的每个组件的基本概念和技术细节:
- 嵌入模型:把要搜索的数据转化为向量的机器学习模型
- 推理API:Elastic中调用模型进行推理的 API
- 生成图像嵌入:调用嵌入模型将图像转化为向量
- 向量搜索:通过向量最近邻搜索实现相似性搜索
- 应用逻辑:前端程序与后端向量搜索引擎Elasticsearch通信
嵌入模型
要将相似性搜索应用于自然语言或图像数据,你需要使用机器学习模型将数据转换为数值表示,也称为向量嵌入(embeddings)。 在这个例子中:
- NLP “transformer” 模型将自然语言转化为向量。
- OpenAI CLIP(对比语言 - 图像预训练)模型对图像进行向量化。
NLP Transformer 模型是经过训练处理自然语言数据的机器学习模型,例如语言翻译、文本分类或命名实体识别。 他们接受了大量的带注释文本数据集的训练,以学习人类语言的模式和结构。
图像相似性应用程序根据文本、自然语言描述找到匹配的图像。 要实现这种相似性搜索,你需要一个在文本和图像上都经过训练并且可以将文本查询转换为向量的模型。
CLIP 是 OpenAI 开发的一种可以处理文本和图像的大规模语言模型。给定一小段文本作为输入,该模型被训练来预测图像的文本表示。 这涉及到将图像的视觉和文本表示关联起来的学习过程,然后才能进行准确的预测。
CLIP 的另一个重要方面是它是一个 “零样本” 模型,允许它执行没有经过专门训练的任务。 例如,它可以对训练期间从未见过的语言进行翻译,或者将图像分类到以前从未见过的类别中。 这使得 CLIP 成为一个非常灵活和通用的模型。
推理API
一旦将 NLP 模型加载到 Elasticsearch 中,你就可以处理实际的用户查询。 首先,你需要使用 Elasticsearch _infer API将查询文本转换为向量。 该API提供了一种在 Elastic 中原生使用 NLP 模型的内置方法,不需要查询外部服务,从而显著简化了实施。
POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/deployment/_infer { "docs" : [ {"text_field": "A mountain covered in snow"} ] }
生成图像嵌入
上面提到的图像嵌入对于图像相似性搜索的效果至关重要。 它们应该存储在一个单独的索引中,该索引包含图像向量,在上面的代码中称为 your-image-index。 该索引由每个图像的文档以及上下文字段和图像的密集向量组成。 图像向量表示低维空间中的图像。 相似的图像被映射到这个空间中的附近点。 原始图像可能有几 MB 大,具体取决于其分辨率。
如何生成这些向量的具体细节可能会有所不同。 一般来说,这个过程涉及从图像中提取特征,然后使用数学函数将它们映射到低维空间。 该函数通常在大量图像数据集上进行训练,以学习在低维空间中表示特征的最佳方式。 生成向量是一项一次性任务。
在这个项目中我们将使用 CLIP 模型。 你可能需要为专门的用例训练自定义嵌入模型以实现所需的性能,具体取决于你要分类的图像类型在用于训练 CLIP 模型的公开可用数据中的表现程度。
Elastic 中的嵌入生成需要在数据写入时发生,步骤如下:
- 加载 CLIP 模型。
- 对于每个图像:
- 加载图像。
- 使用模型评估图像。
- 将生成的向量保存到文档中。
- 将文档保存到Elasticsearch 中。
处理后的文档如下所示。 关键部分是存储密集向量表示的字段 image_embedding。
{ "_index": "my-image-embeddings", "_id": "_g9ACIUBMEjlQge4tztV", "_score": 6.703597, "_source": { "image_id": "IMG_4032", "image_name": "IMG_4032.jpeg", "image_embedding": [ -0.3415695130825043, 0.1906963288784027, ..... -0.10289803147315979, -0.15871885418891907 ], "relative_path": "phone/IMG_4032.jpeg" } }
向量相似度搜索
在使用嵌入模型对查询和文档进行向量化后,相似文档是向量空间中查询的最近邻居。 实现该目标的一种流行算法是 k 最近邻 (kNN),它找到与查询向量最近的 k 个向量。 但是,对于你通常在图像搜索应用程序中处理的大型数据集,kNN 需要非常高的计算资源,并可能导致执行时间过长。 作为一种解决方案,近似最近邻 (ANN) 搜索牺牲了完美的准确性,以换取在大规模高维向量空间中高效地执行。
在 Elastic 中,_search API支持精确和近似最近邻搜索。 使用下面的代码进行 kNN 搜索。 它假定 your-image-index 中所有图像的向量都在 image_embedding 字段中。
# Run kNN search against <query-embedding> obtained above POST <your-image-index>/_search { "fields": [...], "knn": { "field": "image_embedding", "k": 5, "num_candidates": 10, "query_vector": <query-embedding> } }
应用逻辑
在这些基本组件的基础上,你最终可以将所有部分组合在一起来实现交互式图像相似性搜索。 让我们从概念上开始,了解当你想要以交互方式检索匹配的图像时需要发生的事情。
对于文本查询,输入可以简单到像 "roses" 这样的单个词,也可以是更广泛的描述,如 “a mountain covered in snow”。 或者你也可以提供一张图片并要求提供与你图片相似的图片。
尽管你使用不同的模式来查询,但两者在底层向量搜索中都是使用相同的步骤执行,即对密集向量表示的文档使用kNN查询。 我们在前面的部分中描述了使 Elasticsearch 能够对大型图像数据集执行非常快速和可扩展的向量搜索的机制。
那么如何实现上述逻辑呢? 在下面的流程中,你可以看到信息是如何流动的:用户发出的查询,作为文本或图像,由嵌入模型向量化 —— 取决于输入类型:NLP 模型用于文本描述,而 CLIP 模型用于图像。两者都将输入转换为它们的向量表示,并将结果存储为 Elasticsearch 中的密集向量类型([number, number, number...])。
然后在 kNN 搜索中使用向量表示来查找相似的向量(图像),这些向量作为结果返回。
推理:用户查询向量化
后台的应用程序会向 Elasticsearch 中的推理 API 发送请求。 对于文本输入,是这样的:
POST _ml/trained_models/sentence-transformers__clip-vit-b-32-multilingual-v1/deployment/_infer { "docs" : [ {"text_field": "A mountain covered in snow"} ] }
对于图像,你可以使用以下简化代码使用 CLIP 模型处理单个图像
model = SentenceTransformer('clip-ViT-B-32') image = Image.open(file_path) embedding = model.encode(image)
你将得到一个 512 长的 Float32 值数组,如下所示:
{ "predicted_value" : [ -0.26385045051574707, 0.14752596616744995, 0.4033305048942566, 0.22902603447437286, -0.15598160028457642, ... ] }
搜索:寻找相似的图片
对于两种类型的输入,搜索工作相同。 将带有 kNN 搜索定义的查询发送到带有图像向量 my-image-embeddings 的索引。 放入先前查询的密集向量 ("query_vector": [ ... ]) 并执行搜索。
GET my-image-embeddings/_search { "knn": { "field": "image_embedding", "k": 5, "num_candidates": 10, "query_vector": [ -0.19898493587970734, 0.1074572503566742, -0.05087625980377197, ... 0.08200495690107346, -0.07852292060852051 ] }, "fields": [ "image_id", "image_name", "relative_path" ], "_source": false }
Elasticsearch 的响应将根据我们的 kNN 搜索查询为你提供存储在 Elasticsearch 中最匹配的图像。
下面的流程总结了交互式应用程序在处理用户查询时所经历的步骤:
- 加载交互式应用程序,它的前端。
- 用户选择他们感兴趣的图像。
- 你的应用程序通过应用 CLIP 模型将图像向量化,并将生成的向量存储为密集向量类型。
- 应用程序在 Elasticsearch 中启动 kNN 查询,它获取向量并返回其最近的邻居。
- 你的应用程序处理响应并呈现一个(或多个)匹配图像。
7. 领取产品资源流程
7.1 申请阿里云账号
- 阿里云注册页 (aliyun.com)
- 注册账号后,需要支付宝实名认证
7.2 领取免费产品注意事项
- 牢记阿里云账号密码,以及领取的各个组件的账号密码
- 领取组件时,所有组件须选择相同地域,如华北2(北京),并尽量使用同一VPC同一可用区,保证组件之间的内网连通。
- 产品开通顺序为:首先开通检索分析服务Elasticsearch后付费实例、然后领取CLB免费试用、最后领取SAE免费试用,产品之间的配置有前后依赖关系
7.3 开通 Elasticsearch 后付费实例
- 访问Elasticsearch购买页面。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)或账号注册(尚无阿里云账号)。
- 成功登录后,在配置Elasticsearch实例信息面板,完成本教程所需的参数配置,如表格所示,未提及的配置保持默认或按需修改。
配置项 |
教程配置 |
商品类型 |
按量付费 |
实例类型 |
通用商业版 |
Elasticsearch版本 |
8.5 本教程的操作和示例均以Elasticsearch 8.5版本为例,其他版本操作和示例可能略有差别,详细信息请参见Elasticsearch快速入门。 |
场景初始化配置 |
通用场景 |
地域和可用区 |
|
数据节点规格 |
4核 8 GB |
数据节点存储类型 |
高效云盘 |
数据单节点存储空间 |
20 GB |
数据节点数量 |
3 |
Kibana规格 |
1核 2 GB |
专有网络 |
选择您已创建的专有网络。如果没有创建,请参见创建和管理专有网络创建。 |
虚拟交换机 |
选择您已创建的虚拟交换机。如果没有创建,请参见创建和管理交换机创建。 |
资源组 |
选择您已创建的资源组,可以选择默认资源组。如果没有创建,请参见创建资源组创建。 |
实例名称 |
test-es |
登录名 |
elastic |
登录密码 |
自定义密码 |
服务协议 |
选中 |
- 单击立即购买,提示开通成功后,按照页面提示进入控制台。
- 在产品列表中选择Elasticsearch,进入阿里云Elasticsearch的控制台的概览页面。
- 在顶部菜单栏,选择购买实例时所配置的地域,本教程为华北2(北京)。在实例列表中查看创建成功的实例及其状态。
实例创建后,大约需要5分钟生效。等待实例生效且状态变为正常,才可继续执行后续步骤。
7.4 如何领取CLB免费试用
传统型负载均衡CLB免费试用领取地址:
https://free.aliyun.com/?pipCode=slb
7.5 如何领取 SAE 免费试用
- 如果您是SAE新客,建议领取SAE免费试用资源,可抵扣3个月内的CPU和内存消耗,领取地址:https://free.aliyun.com/?searchKey=sae
- 如果您是SAE老用户,可以选择使用个人资源,会产生一定费用,以2核4G的实例为例,花费是0.0074074元/分钟
8. 项目开发
8.1 创建配置 Elasticsearch 部分
- 进入控制台,找到Elasticsearch所在的地域,从实例列表页找到实验需要使用ES的实例:
- 点击实例ID或“管理”,进入实例详情页,可查看ES的实例所在的专有网络、私网地址、私网端口等信息;
- 进入安全配置,确认VPC私网访问白名单是否包含ES实例所在的专有网络的全部网段:
专有网络网段可以进入专有网络列表页查看:https://vpc.console.aliyun.com/vpc/
- 进入可视化控制,在修改配置页修改Kibana公网访问白名单为本机IP:
- 点击公网入口进入kibana,正确输入用户名密码后,即可登录。用户名默认为:elastic;密码为实例创建时输入的自定义密码。
- 左侧菜单栏“Management”进入“开发工具”
- 通过快照恢复方式将数据集和模型导入到ES实验实例中:
1)创建快照仓库并指定公共读的阿里云OSS bucket作为源存储库
代码:
PUT _snapshot/my_backup/ { "type": "oss", "settings": { "endpoint": "http://oss-rg-china-mainland.aliyuncs.com", "bucket": "es-image-search", "base_path": "snapshot/", "readonly": true, "access_key_id": "xxxx", "secret_access_key":"xxxx", "region": "oss-rg-china-mainland" } }
说明:“access_key_id”和“secret_access_key”字段的具体信息,可进入钉钉群(群号:28810034388)在群公告处获取。
2)从公共读的OSS中恢复快照到当前实验实例中:
代码:
POST /_snapshot/my_backup/snapshot_1/_restore { "indices": "image-embeddings", "feature_states": ["machine_learning"], "ignore_unavailable": true, "include_global_state": false }
3)确认数据已同步完毕:
左侧菜单栏“Management”进入“Stack Management”的“索引管理”模块,确认“image-embeddings”和".ml-inference-native-000001"大小和下图一致:
- 左侧菜单栏“Analytics”进入“Machine Learning”中“同步模型”后进入“模型管理-已训练模型”并部署
tips:如遇以下网络返回超时报错可忽略,关闭报错窗口并刷新,模型状态能正常更新为“started”即可。
- 测试模型,输入词组或短句,该模型可以将文本数据转换成向量数据:
该模型支持中英文的文本转换,成功转化为向量后,说明模型部署成功。
8.2 创建和配置 SAE 部分
本步骤仅介绍关键配置项,其余配置项保持默认即可。
- 登录SAE控制台。
- (可选)在左侧导航栏,单击命名空间(环境),在顶部菜单栏选择华北2(北京)地域,然后在命名空间页面,单击创建命名空间,在创建命名空间面板,配置相关信息,单击确定。
配置项 |
教程配置 |
命名空间名称 |
自定义,例如输入demo。 |
命名空间ID |
自定义,例如输入demo。 |
描述 |
自定义,例如输入测试。 |
说明:如果跳过该步骤,在创建应用时(步骤4)选择默认命名空间,则应用创建成功后,需要切换VPC,修改为与Elasticsearch实例配置一致的VPC。
- 在左侧导航栏,选择应用管理>应用列表,然后在应用列表页面,单击创建应用。
- 在创建应用页面,配置相关信息。
- 在应用基本信息配置向导,配置相关信息,然后单击下一步:应用部署配置。
配置项 |
教程配置 |
应用名称 |
自定义,例如输入demo。 |
专有网络配置 |
选择自定义配置。 |
命名空间 |
更多信息,请参见管理命名空间。 |
vSwitch |
选择与Elasticsearch实例配置一致的虚拟交换机。 |
安全组 |
选择与Elasticsearch实例配置一致的VPC绑定的安全组。更多信息,请参见创建安全组。 |
应用实例数 |
1 |
VCPU |
2Core |
内存 |
4GiB |
- 在应用部署配置配置向导,配置相关信息,然后单击下一步:确认规格。
配置项 |
教程配置 |
技术栈语言 |
选择Python。 |
应用部署方式 |
选择镜像。 |
配置镜像 |
在配置镜像区域,单击Demo镜像页签,选择SAE提供的版本为nlp的镜像Demo。完整的镜像地址如下: registry-vpc.cn-beijing.aliyuncs.com/sae-serverless-demo/python-demo:nlp |
环境变量设置 |
展开环境变量设置区域,选择类型为自定义,新增3对键值对,格式如下:
|
注意事项如下:
ES_HOST可在阿里云Elasticsearch控制台的实例基本信息页面获取ES实例的私网地址。
请注意格式为:http://es-cn-vxxxxx.elasticsearch.aliyuncs.com:9200
ES_USER和ES_PWD为开通Elasticsearch时填写的的账户名和密码。
- 在确认规格配置向导,查看您所创建应用的详细信息以及费用配置情况,然后单击确认创建。
- 页面会跳转至创建完成配置向导,您可以单击应用详情页进入基本信息页面。
8.3 为 SAE 应用绑定负载均衡 CLB
SAE支持绑定的SLB,为传统型负载均衡CLB(Classic Load Balancer),属于阿里云负载均衡SLB(Server Load Balancer)支持的负载均衡类型之一。
1、在应用的基本信息页面的应用访问设置区域,单击添加公网SLB访问。
2、在添加公网访问SLB对话框,从请选择SLB下拉列表中,选择复用已创建的免费试用CLB资源(优先),或者新建SLB资源(如果没有CLB领取资格需要额外付费),然后在HTTP协议页签,HTTP端口输入80,容器端口输入5001,单击确认。
注意:如果您复用已创建的SLB,且需要确保HTTP端口和容器端口均未被占用。更多信息,请参见CLB按量付费。
3、添加完成后,您可以在公网访问地址栏看到该公网SLB的IP地址和端口。
4、在浏览器地址栏中输入上一步获得的 SLB的IP地址:端口,并回车访问公网。在如下界面中,我们可以在搜索框中输入文字搜索图片,或者在图片结果列的“搜索相似图片”按钮,搜索相似图片。下图红色框的内容展现了搜索相似图片的实现原理。