基于火山引擎云搜索的混合搜索实战

在搜索应用中,传统的 Keyword Search 一直是主要的搜索方法,它适合精确匹配查询的场景,能够提供低延迟和良好的结果可解释性,但是 Keyword Search 并没有考虑上下文信息,可能产生不相关的结果。最近几年,基于向量检索技术的搜索增强技术 Semantic Search 越来越流行,通过使用机器学习模型将数据对象(文本、图像、音视频等)转化成向量,向量距离代表对象间的相似性,如果使用的模型和问题领域相关性高,则往往能更好地理解上下文和搜索意图,进而提高搜索结果的相关性,反之,如果模型和问题领域相关性不高,则效果会大打折扣。

Keyword Search 和 Semantic Search 都存在明显的优劣势,那么是否可以通过组合它们的优点来整体提高搜索的相关性?答案是,简单的算术组合并不能收到预期的效果,主要原因有两个:

  • 首先是不同类型查询的评分并不在同一个可比较的维度,因此不能直接进行简单的算术计算。

  • 其次是在分布式检索系统中,评分通常在分片级别,需要对所有分片的评分进行全局归一化处理。

综上,我们需要寻找一种理想的查询类型来解决这些问题,它能单独执行每个查询子句,同时收集分片级别的查询结果,最后对所有查询的评分进行归一化合并后返回最终的结果,这就是混合搜索(Hybrid Search) 方案。

通常一次混合搜索查询可以分为以下几步:

  1. 查询阶段:使用混合查询子句进行 Keyword Search 和 Semantic Search。

  2. 评分归一化和合并阶段,该阶段在查询阶段之后。

    1. 由于每种查询类型都会提供不同范围的评分,该阶段对每一个查询子句的评分结果执行归一化操作,支持的归一化方法有 min_max、l2、rrf。

    2. 对归一化后的评分进行组合,组合方法有 arithmetic_mean、geometric_mean、harmonic_mean。

  3. 根据组合后的评分对文档重新排序并返回给用户。

实现思路

从前面原理介绍,我们可以看到要实现一个混合检索应用,至少需要用到这些基础技术设施

  • 全文检索引擎

  • 向量检索引擎

  • 用于向量 Embedding 的机器学习模型

  • 将文本、音频、视频等数据转化成向量的数据管道

  • 融合排序

火山引擎云搜索构建在开源的 Elasticsearch 和 OpenSearch 项目上,从第一天上线就支持了完善成熟的文本检索和向量检索能力,同时针对混合搜索场景也进行了一系列的功能迭代和演进,提供了开箱即用的混合搜索解决方案。本文将以图像搜索应用为例,介绍如何借助火山引擎云搜索服务的解决方案快速开发一个混合搜索应用。

其端到端流程概括如下:

  1. 配置创建相关对象

    1. Ingestion Pipeline:支持自动调用模型把图片转换向量并存到索引中

    2. Search Pipeline:支持把文本查询语句自动转换成向量以便进行相似度计算

    3. k-NN索引:存放向量的索引

  2. 将图像数据集数据写入 OpenSearch 实例,OpenSearch 会自动调用机器学习模型将文本转为 Embedding 向量。

  3. Client 端发起混合搜索查询时,OpenSearch 调用机器学习模型将传入的查询转为 Embedding 向量。

  4. OpenSearch 执行混合搜索请求处理,组合 Keyword Seach 和 Semantic Seach 的评分,返回搜索结果。

方案实战

环境准备

1.登录火山引擎云搜索服务(https://console.volcengine.com/es),创建实例集群,版本选择 OpenSearch 2.9.0。

2.待实例创建完毕,启用 AI 节点。

3.在模型选择上,可以创建自己的模型,也可以选择公共模型。这里我们选择公共模型,完成配置后,点击立即启动

至此,准备好了 OpenSearch 实例和混合搜索所依赖的机器学习服务。

数据集准备

使用 Amazon Berkeley Objects Dataset(https://registry.opendata.aws/amazon-berkeley-objects/)作为数据集,数据集无需本地下载,直接通过代码逻辑上传到 OpenSearch,详见下面代码内容。

操作步骤

安装 Python 依赖

pip install -U elasticsearch7==7.10.1
pip install -U pandas
pip install -U jupyter
pip install -U requests
pip install -U s3fs
pip install -U alive_progress
pip install -U pillow
pip install -U ipython

连接到 OpenSearch

# Prepare opensearch info
from elasticsearch7 import Elasticsearch as CloudSearch
from ssl import create_default_context
# opensearch info
opensearch_domain = '{{ OPENSEARCH_DOMAIN }}'
opensearch_port = '9200'
opensearch_user = 'admin'
opensearch_pwd = '{{ OPENSEARCH_PWD }}'
# remote config for model server
model_remote_config = {"method": "POST","url": "{{ REMOTE_MODEL_URL }}","params": {},"headers": {"Content-Type": "application/json"},"advance_request_body": {"model": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"}
}
# dimension for knn vector
knn_dimension = 384
# load cer and create ssl context
ssl_context = create_default_context(cafile='./ca.cer')
# create CloudSearch client
cloud_search_cli = CloudSearch([opensearch_domain, opensearch_port],ssl_context=ssl_context,scheme="https",http_auth=(opensearch_user, opensearch_pwd))
# index name
index_name = 'index-test'# pipeline id
pipeline_id = 'remote_text_embedding_test'
# search pipeline id
search_pipeline_id = 'rrf_search_pipeline_test'

1.填入 OpenSearch 链接地址和用户名密码信息。model_remote_config 是远程机器学习模型连接配置,可在模型调用信息查看,将调用信息中的 remote_config 配置全部复制到 model_remote_config

2.在实例信息->服务访问部分,下载证书到当前目录。

3.给定索引名称、Pipeline ID 和 Search Pipeline ID。

创建 Ingest Pipeline

创建 Ingest Pipeline,指定使用的机器学习模型,将指定字段转换为向量后嵌入回去。如下,将 caption 字段转为向量存储到 caption_embedding 中。

# Create ingest pipeline
pipeline_body = {"description": "text embedding pipeline for remote inference","processors": [{"remote_text_embedding": {"remote_config": model_remote_config,"field_map": {"caption": "caption_embedding"}}}]
}
# create request
resp = cloud_search_cli.ingest.put_pipeline(id=pipeline_id, body=pipeline_body)
print(resp)

创建 Search Pipeline

创建查询需要使用的 Pipeline,配置好远程模型。

支持的归一化方法和加权求和方法:

  • 归一化方法:min_maxl2rrf

  • 加权求和方法:arithmetic_meangeometric_meanharmonic_mean

这里选择 rrf 归一化方法。

# Create search pipeline
import requests
search_pipeline_body = {"description": "post processor for hybrid search","request_processors": [{"remote_embedding": {"remote_config": model_remote_config}}],"phase_results_processors": [  # normalization and combination{"normalization-processor": {"normalization": {"technique": "rrf",  # the normalization technique in the processor is set to rrf"parameters": {"rank_constant": 60  # param}},"combination": {"technique": "arithmetic_mean",  # the combination technique is set to arithmetic mean"parameters": {"weights": [0.4,0.6]}}}}]
}
headers = {'Content-Type': 'application/json',
}
# create request
resp = requests.put(url="https://" + opensearch_domain + ':' + opensearch_port + '/_search/pipeline/' + search_pipeline_id,auth=(opensearch_user, opensearch_pwd),json=search_pipeline_body,headers=headers,verify='./ca.cer')
print(resp.text)

创建 k-NN 索引

  1. 将事先创建好的 Ingest Pipeline 配置到 index.default_pipeline 字段中;

  2. 同时,配置 properties,将 caption_embedding 设置为 knn_vector,这里使用 faiss 中的 hnsw。

# Create k-NN index
# create index and set settings, mappings, and properties as needed.
index_body = {"settings": {"index.knn": True,"number_of_shards": 1,"number_of_replicas": 0,"default_pipeline": pipeline_id  # ingest pipeline},"mappings": {"properties": {"image_url": {"type": "text"},"caption_embedding": {"type": "knn_vector","dimension": knn_dimension,"method": {"engine": "faiss","space_type": "l2","name": "hnsw","parameters": {}}},"caption": {"type": "text"}}}
}
# create index
resp = cloud_search_cli.indices.create(index=index_name, body=index_body)
print(resp)

加载数据集

读取数据集到内存中,并过滤出部分需要使用的数据。

# Prepare dataset
import pandas as pd
import string
appended_data = []
for character in string.digits[0:] + string.ascii_lowercase:if character == '1':breaktry:meta = pd.read_json("s3://amazon-berkeley-objects/listings/metadata/listings_" + character + ".json.gz",lines=True)except FileNotFoundError:continueappended_data.append(meta)
appended_data_frame = pd.concat(appended_data)
appended_data_frame.shape
meta = appended_data_frame
def func_(x):us_texts = [item["value"] for item in x if item["language_tag"] == "en_US"]return us_texts[0] if us_texts else None
meta = meta.assign(item_name_in_en_us=meta.item_name.apply(func_))
meta = meta[~meta.item_name_in_en_us.isna()][["item_id", "item_name_in_en_us", "main_image_id"]]
print(f"#products with US English title: {len(meta)}")
meta.head()
image_meta = pd.read_csv("s3://amazon-berkeley-objects/images/metadata/images.csv.gz")
dataset = meta.merge(image_meta, left_on="main_image_id", right_on="image_id")
dataset.head()

上传数据集

上传数据集到 Opensearch,针对每条数据,传入 image_url 和 caption。无需传入 caption_embedding,将通过远程机器学习模型自动生成。

# Upload dataset
import json
from alive_progress import alive_bar
cnt = 0
batch = 0
action = json.dumps({"index": {"_index": index_name}})
body_ = ''with alive_bar(len(dataset), force_tty=True) as bar:for index, row in (dataset.iterrows()):if row['path'] == '87/874f86c4.jpg':continuepayload = {}payload['image_url'] = "https://amazon-berkeley-objects.s3.amazonaws.com/images/small/" + row['path']payload['caption'] = row['item_name_in_en_us']body_ = body_ + action + "\n" + json.dumps(payload) + "\n"cnt = cnt + 1if cnt == 100:resp = cloud_search_cli.bulk(request_timeout=1000,index=index_name,body=body_)cnt = 0batch = batch + 1body_ = ''bar()
print("Total Bulk batches completed: " + str(batch))

混合搜索查询

以查询 shoes 为例,查询中包含两个查询子句,一个是 match 查询,一个是 remote_neural 查询。查询时将事先创建好的 Search Pipeline 指定为查询参数,Search Pipeline 会将传入的文本转为向量,存储到 caption_embedding 字段,用于后续查询。

# Search with search pipeline
from urllib import request
from PIL import Image
import IPython.display as display
def search(text, size):resp = cloud_search_cli.search(index=index_name,body={"_source": ["image_url", "caption"],"query": {"hybrid": {"queries": [{"match": {"caption": {"query": text}}},{"remote_neural": {"caption_embedding": {"query_text": text,"k": size}}}]}}},params={"search_pipeline": search_pipeline_id},)return resp
k = 10
ret = search('shoes', k)
for item in ret['hits']['hits']:display.display(Image.open(request.urlopen(item['_source']['image_url'])))print(item['_source']['caption'])

混合搜索演示

以上就是以图像搜索应用为例,介绍如何借助火山引擎云搜索服务的解决方案快速开发一个混合搜索应用的实战过程,欢迎大家登陆火山引擎控制台操作!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/838244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单文件组件,为什么要使用 SFC

介绍 Vue 的单文件组件 (即 *.vue 文件&#xff0c;英文 Single-File Component&#xff0c;简称 SFC) 是一种特殊的文件格式&#xff0c;使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。下面是一个单文件组件的示例&#xff1a; <script setup> impor…

机器学习_朴素贝叶斯

机器学习_朴素贝叶斯 朴素贝叶斯算法&#xff08;Naive Bayes Algorithm&#xff09;是一种基于贝叶斯定理与特征条件独立假设的分类方法。该算法假设给定目标值时&#xff0c;各个特征之间相互独立。朴素贝叶斯算法通过训练数据集学习联合概率分布&#xff0c;并基于此模型&a…

优秀博士学位论文分享:复杂场景下高精度有向目标检测的研究

优秀博士学位论文代表了各学科领域博士研究生研究成果的最高水平&#xff0c;本公众号近期将推出“优秀博士学位论文分享”系列文章&#xff0c;对人工智能领域2023年优秀博士学位论文进行介绍和分享&#xff0c;方便广大读者了解人工智能领域最前沿的研究进展。 “博士学位论…

C++11 新特性 常量表达式 constexpr

为了解决常量无法确定的问题&#xff0c;C11在新标准中提出了关键字constexpr&#xff0c;它能够有效地定义常量表达式&#xff0c;并且达到类型安全、可移植、方便库和嵌入式系统开发的目的。 一、常量的不确定性 在C11标准以前&#xff0c;我们没有一种方法能够有效地要求一…

UBUNTU下CMAKE指定执行文件运行时查找库的路径

在Ubuntu下&#xff0c;使用CMake时&#xff0c;如果需要指定执行文件运行时库的搜索路径&#xff0c;可以在CMakeLists.txt文件中通过set_target_properties命令来设置。 以下是一个示例&#xff0c;假设你的目标是一个名为my_application的可执行文件&#xff0c;你想要添加…

LLama3大模型本地部署 仅需6步完成对话模型本地安装部署。附送可视化ui安装、自定义模型目录,修改模型保存地址,第三方微调模型、中文模型下载地址

本篇分为三部分 一&#xff1a;6步完成llama3大模型本地部署 二&#xff1a;8步完成llama3可视化对话界面安装 三&#xff1a;重设模型文件路径 四&#xff1a;微调模型、中文模型下载资源分享 一、LLama3 大模型本地部署安装 首先去mata官网下载ollama客户端 Ollama 选择合适…

如何使用正则表达式避免生成空字符串

在字符串处理中&#xff0c;我们经常需要将字符串根据特定的分隔符拆分成多个子字符串。Java 中的 split 方法可以很好地完成这项任务。但是&#xff0c;在使用 split 方法时&#xff0c;如果分隔符连续出现&#xff0c;可能会生成空字符串。 可以使用正则表达式避免生成空字符…

linux 环境下 分布式文件搭建fastDFS

1.软件信息 地址&#xff1a;happyfish100 (YuQing) GitHub 1.fastdfs-master.zip 2.fastdfs-nginx-module-master.zip 3.libfastcommon-master.zip 4.libserverframe-master.zip yum install make cmake gcc gcc-c perl 2.安装libfastcommon unzip libfastcommon-mast…

MQTT_客户端安装_1.4

下载地址 MQTTX 下载 下一步直接安装即可 界面介绍

人工智能项目,如何解决大模型的数据私有化

这个问题是最近走访百家企业&#xff0c;客户问的最多的问题。人工智能是对数据集中后&#xff0c;再利用的智能化手段&#xff0c;ChatGPT还在持续的投入&#xff0c;汇集数据、训练模型&#xff0c;微软也不过是做了一个办公客户端的智能工具&#xff0c;那么行业应运之时&am…

基于CentOS-7搭建hadoop3.3.6大数据集群(保姆级教程)

目录 安装虚拟机 为hadoop用户添加权限 关闭防火墙 修改主机名以及ip地址映射 配置ip 连接xshell &#xff0c;以hadoop用户登录 创建目录并将该文件夹权限赋予hadoop用户 安装配置jdk 关闭虚拟机&#xff0c;克隆其他两个节点 修改主机名和ip地址 配置免密登录 安装…

如何通过专业的二手机店erp优化手机商家运营!

在数字化浪潮席卷全球的大背景下&#xff0c;手机行业作为科技发展的前沿阵地&#xff0c;正经历着前所未有的变革。对于众多手机商家而言&#xff0c;如何在这场变革中抢占先机&#xff0c;实现数字化转型&#xff0c;成为了摆在他们面前的一大难题。幸运的是&#xff0c;途渡…

工作绩效域怎么写和子题目如何回应

某智慧案管信息化系统 在2023年11月&#xff0c;我作为项目经理&#xff0c;领导了“某市XX智慧案管信息化系统”项目的建设工作。该项目以485.5万元的合同金额成功中标&#xff0c;预计建设周期为12个月。作为一个多维度的系统工程&#xff0c;它由案件受理、分配、跟踪、审理…

python如何在图片上写斜体字

在Python中&#xff0c;直接在图片上写斜体文字通常不是图像库&#xff08;如PIL或OpenCV&#xff09;的内置功能&#xff0c;因为这些库主要关注于图像处理而非复杂的文本渲染。然而&#xff0c;你可以通过几种方式在图片上创建斜体效果&#xff1a; 使用PIL&#xff08;Pytho…

API低代码平台介绍3-异构数据源的数据查询功能

异构数据源的数据查询功能 在上一篇文章中我们通过API平台定义了一个最基本的数据查询接口&#xff0c;本篇文章我们将上升难度&#xff0c;在原有接口的基础上&#xff0c;实现在MySQL数据库和Oracle数据库同时进行数据查询。   什么场景会需要同时对异构数据源进行查询&…

基于FPGA的NC图像质量评估verilog实现,包含testbench和MATLAB辅助验证程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 vivado2019.2和matlab2022a测试&#xff0c;结果如下&#xff1a; 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale …

【C语言习题】6.逆序输出

文章目录 1.描述输入描述&#xff1a;输出描述&#xff1a;示例图&#xff1a; 2.解题思路3.具体代码4.代码讲解 1.描述 输入10个整数&#xff0c;要求按输入时的逆序把这10个数打印出来。逆序输出&#xff0c;就是按照输入相反的顺序打印这10个数。 输入描述&#xff1a; 一…

苹果与谷歌联合推出跨平台反跟踪器

近日&#xff0c;苹果公司发布了iOS 17.5&#xff0c;新版本新增了跨平台的反追踪检测功能。这一功能是与谷歌合作开发的&#xff0c;意味着苹果的“查找我的”和谷歌的新“查找我的设备”网络将携手合作&#xff0c;共同抵制不必要的追踪和骚扰行为。如果检测到非你所有的追踪…

SDL系列(三)—— SDL2.0 扩展库:SDL_image与SDL_mixer

SDL_image SDL 默认支持的&#xff0c;只能打开 BMP 格式的图片 。 然而我们常见的是 Png jpg 格式的图片&#xff0c;于是我们这节完成 SDL 借用 自带的三方库 &#xff0c;来 完成加载渲染 png 等其他图片格式。 SDL_image 简介 使用 SDL_image &#xff0c;您…

自动驾驶技术:现状、挑战与前景

自动驾驶技术是当今汽车行业的热门话题&#xff0c;它的发展前景备受关注&#xff0c;同时也面临着诸多挑战和限制。在这篇文章中&#xff0c;我将探讨自动驾驶技术的现状、挑战&#xff0c;并展望其未来的发展前景。 现状&#xff1a; 自动驾驶技术已经取得了一定的进…