商城网站建设网络公司,现在哪个公司家庭网络好用,网络热词大全,个人网站赏析在搜索应用中#xff0c;传统的 Keyword Search 一直是主要的搜索方法#xff0c;它适合精确匹配查询的场景#xff0c;能够提供低延迟和良好的结果可解释性#xff0c;但是 Keyword Search 并没有考虑上下文信息#xff0c;可能产生不相关的结果。最近几年#xff0c;基…在搜索应用中传统的 Keyword Search 一直是主要的搜索方法它适合精确匹配查询的场景能够提供低延迟和良好的结果可解释性但是 Keyword Search 并没有考虑上下文信息可能产生不相关的结果。最近几年基于向量检索技术的搜索增强技术 Semantic Search 越来越流行通过使用机器学习模型将数据对象(文本、图像、音视频等)转化成向量向量距离代表对象间的相似性如果使用的模型和问题领域相关性高则往往能更好地理解上下文和搜索意图进而提高搜索结果的相关性反之如果模型和问题领域相关性不高则效果会大打折扣。
Keyword Search 和 Semantic Search 都存在明显的优劣势那么是否可以通过组合它们的优点来整体提高搜索的相关性答案是简单的算术组合并不能收到预期的效果主要原因有两个 首先是不同类型查询的评分并不在同一个可比较的维度因此不能直接进行简单的算术计算。 其次是在分布式检索系统中评分通常在分片级别需要对所有分片的评分进行全局归一化处理。
综上我们需要寻找一种理想的查询类型来解决这些问题它能单独执行每个查询子句同时收集分片级别的查询结果最后对所有查询的评分进行归一化合并后返回最终的结果这就是混合搜索(Hybrid Search) 方案。 通常一次混合搜索查询可以分为以下几步 查询阶段使用混合查询子句进行 Keyword Search 和 Semantic Search。 评分归一化和合并阶段该阶段在查询阶段之后。 由于每种查询类型都会提供不同范围的评分该阶段对每一个查询子句的评分结果执行归一化操作支持的归一化方法有 min_max、l2、rrf。 对归一化后的评分进行组合组合方法有 arithmetic_mean、geometric_mean、harmonic_mean。 根据组合后的评分对文档重新排序并返回给用户。
实现思路
从前面原理介绍我们可以看到要实现一个混合检索应用至少需要用到这些基础技术设施 全文检索引擎 向量检索引擎 用于向量 Embedding 的机器学习模型 将文本、音频、视频等数据转化成向量的数据管道 融合排序
火山引擎云搜索构建在开源的 Elasticsearch 和 OpenSearch 项目上从第一天上线就支持了完善成熟的文本检索和向量检索能力同时针对混合搜索场景也进行了一系列的功能迭代和演进提供了开箱即用的混合搜索解决方案。本文将以图像搜索应用为例介绍如何借助火山引擎云搜索服务的解决方案快速开发一个混合搜索应用。 其端到端流程概括如下 配置创建相关对象 Ingestion Pipeline支持自动调用模型把图片转换向量并存到索引中 Search Pipeline支持把文本查询语句自动转换成向量以便进行相似度计算 k-NN索引存放向量的索引 将图像数据集数据写入 OpenSearch 实例OpenSearch 会自动调用机器学习模型将文本转为 Embedding 向量。 Client 端发起混合搜索查询时OpenSearch 调用机器学习模型将传入的查询转为 Embedding 向量。 OpenSearch 执行混合搜索请求处理组合 Keyword Seach 和 Semantic Seach 的评分返回搜索结果。
方案实战
环境准备
1.登录火山引擎云搜索服务https://console.volcengine.com/es创建实例集群版本选择 OpenSearch 2.9.0。
2.待实例创建完毕启用 AI 节点。 3.在模型选择上可以创建自己的模型也可以选择公共模型。这里我们选择公共模型完成配置后点击立即启动。 至此准备好了 OpenSearch 实例和混合搜索所依赖的机器学习服务。
数据集准备
使用 Amazon Berkeley Objects Datasethttps://registry.opendata.aws/amazon-berkeley-objects/作为数据集数据集无需本地下载直接通过代码逻辑上传到 OpenSearch详见下面代码内容。
操作步骤
安装 Python 依赖
pip install -U elasticsearch77.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_contextssl_context,schemehttps,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(idpipeline_id, bodypipeline_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 rrfparameters: {rank_constant: 60 # param}},combination: {technique: arithmetic_mean, # the combination technique is set to arithmetic meanparameters: {weights: [0.4,0.6]}}}}]
}
headers {Content-Type: application/json,
}
# create request
resp requests.put(urlhttps:// opensearch_domain : opensearch_port /_search/pipeline/ search_pipeline_id,auth(opensearch_user, opensearch_pwd),jsonsearch_pipeline_body,headersheaders,verify./ca.cer)
print(resp.text)
创建 k-NN 索引 将事先创建好的 Ingest Pipeline 配置到 index.default_pipeline 字段中 同时配置 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(indexindex_name, bodyindex_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,linesTrue)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_usmeta.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_onmain_image_id, right_onimage_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_ttyTrue) 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) \ncnt cnt 1if cnt 100:resp cloud_search_cli.bulk(request_timeout1000,indexindex_name,bodybody_)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(indexindex_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]) 混合搜索演示 以上就是以图像搜索应用为例介绍如何借助火山引擎云搜索服务的解决方案快速开发一个混合搜索应用的实战过程欢迎大家登陆火山引擎控制台操作