Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索

152 阅读8分钟

68c04d38acfe4814baa4fa8b2920bea9.png 在之前的文章 “Elasticsearch 开放推理 API 新增阿里云 AI 搜索支持”,它详细描述了如何使用 Elastic inference API 来针对阿里的密集向量模型,稀疏向量模型, 重新排名及 completion 进行展示。在那篇文章里,它使用了很多的英文的例子。我觉得阿里的模型更适合中文字来进行展示。我们知道 Elastic 的开箱即用的稀疏向量模型 ELSER 只适合英文。目前它不支持中文。恰好阿里的稀疏向量模型填补了这个空白。稀疏向量可以开箱即用。对于很多不是很精通人工智能的开发者来说,这无疑是个福音,而且它使用的资源很小。

更多阅读,请参阅 “阿里云 AI 搜索推理服务”。

稀疏向量

根据文档,我们使用如下的命令来创建稀疏向量的推理 API 端点:



1.  PUT _inference/sparse_embedding/alibabacloud_ai_search_sparse
2.  {
3.      "service": "alibabacloud-ai-search",
4.      "service_settings": {
5.          "api_key": "<api_key>",
6.          "service_id": "ops-text-sparse-embedding-001",
7.          "host": "default-j01.platform-cn-shanghai.opensearch.aliyuncs.com",
8.          "workspace": "default"
9.      }
10.  }


在上面,我们需要从阿里云获得 api_key 来进行。运行上面的命令:

1d5341a395ad47079e8fdf82bda4f20f.png

我们接下来可以通过如下的方式来测试:



1.  POST _inference/alibabacloud_ai_search_sparse
2.  {
3.    "input": "阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳"
4.  }


上面的命令显示的结果为:

c7cf0e81347a41f081d10675d2a2ae91.png

我们从上面的显示结果可以看出来,它和我们之前的 Elastic ELSER 输出是不同的。这里应该是 unicode。

20f5185061784441a1501dcf94282acc.png

上面的命令和下面的命令是一样的:



1.  POST _inference/sparse_embedding/alibabacloud_ai_search_sparse
2.  {
3.    "input": "阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳"
4.  }


因为每个 endpoint 在 Elasticsearch 创建时,都会自动检测并识别出它是什么类型的模型,所以上面路径中的 sparse_embedding 是可以省去的。

密集向量

同样,根据文档,我们使用如下的命令来创密集向量的推理 API 端点:



1.  PUT _inference/text_embedding/alibabacloud_ai_search_embeddings
2.  {
3.      "service": "alibabacloud-ai-search",
4.      "service_settings": {
5.          "api_key": "<api_key>",
6.          "service_id": "ops-text-embedding-001",
7.          "host": "default-j01.platform-cn-shanghai.opensearch.aliyuncs.com",
8.          "workspace": "default"
9.      }
10.  }


运行上面的命令,我们可以看到:

50c747112bca4c41b754be3246a3ca0b.png 我们可以使用如下的命令来生成密集向量:



1.  POST _inference/alibabacloud_ai_search_embeddings
2.  {
3.    "input": "阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳"
4.  }


f04d3a404e9040a68bffecc2354309cd.png

密集向量是一个浮点数的数组。我们在生成的时候,其实还是可以对它进行标量量化,这样可以节省内存消耗,并提高搜索的速度。

完成 - completion

我们甚至可以针对搜索的结果运用大模型来得到一个 completion 的结果,比如,我们使用如下的命令来生成一个 completion 的推理 API 端点:



1.  PUT _inference/completion/alibabacloud_ai_search_completion
2.  {
3.      "service": "alibabacloud-ai-search",
4.      "service_settings": {
5.          "host" : "default-j01.platform-cn-shanghai.opensearch.aliyuncs.com",
6.          "api_key": "{{API_KEY}}",
7.          "service_id": "ops-qwen-turbo",
8.          "workspace" : "default"
9.      }
10.  }


355e139be7ca4eaa867a80fb8824db4c.png

我们可以通过如下的例子来展示 completion:

effc65cae4884988a7ae231f8b747555.png

这个结果是结合大模型而生成的。大模型提供了一个基于在大模型训练时得到的结果。

重新排名 - rerank

同样,我们可以按照如下的命令来生成一个 rerank 的推理 API 端点:



1.  PUT _inference/rerank/alibabacloud_ai_search_rerank
2.  {
3.      "service": "alibabacloud-ai-search",
4.      "service_settings": {
5.          "api_key": "<api_key>",
6.          "service_id": "ops-bge-reranker-larger",
7.          "host": "default-j01.platform-cn-shanghai.opensearch.aliyuncs.com",
8.          "workspace": "default"
9.      }
10.  }


f1ecb8e7c63e4f95b9112baec69b84f5.png

我们可以使用如下的例子来进行展示:



1.  POST _inference/alibabacloud_ai_search_rerank
2.  {
3.    "query": "阿里巴巴(中国)有限公司是哪一年成立的?",
4.    "input": [
5.       "阿里巴巴是全球领先的B2B电子商务网上贸易平台",
6.       "阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳"
7.    ]
8.  }


在上面的 input 里,我们列举了两个文档。我们可以通过 rerank 端点来针对这两个文档重新进行排序。假如我们想搜索的文字是 “阿里巴巴(中国)有限公司是哪一年成立的?”。那么 rerank 返回来的结果是:

49eed8f7a2e149acb1f060186b6e0bd5.png

从上面,我们可以看出来,第二个文档比第一个文档更为贴近,也就是它的相关度更高。

RAG 应用

在很多情况下,我们企业有很多的业务数据或者私有数据每时每刻都在生成,而大模型的知识仅限于在它生成的时候,所以很多的时候,大模型有很多的知识是不知道的。如果我们不对大模型的回答进行限制,那么它可能给出的答案就是错误的,从而产生幻觉。在实际的应用中,我们通常把业务或私有数据保存于像 Elasticsearch 这样的向量数据库中。在搜索时,我们首先搜索 Elasticsearch,并把搜索的结果发送给大模型做为 prompt 的一部分,这样就可以解决幻觉的问题。

e8a4b995c9e1426f93ef5589b2c6af68.png 首先,我们来创建一个稀疏向量索引:



1.  PUT alibaba_sparse
2.  {
3.    "mappings": {
4.      "properties": {
5.        "inference_field": {
6.          "type": "semantic_text",
7.          "inference_id": "alibabacloud_ai_search_sparse"
8.        }
9.      }
10.    }
11.  }


然后,我们写入如下的两个文档:



1.  PUT alibaba_sparse/_bulk
2.  {"index": {"_id": "1"}}
3.  {"inference_field": "阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳"}
4.  {"index": {"_id": "2"}}
5.  {"inference_field": "百度是拥有强大互联网基础的领先AI公司。百度愿景是:成为最懂用户,并能帮助人们成长的全球顶级高科技公司。于2000年1月1日在中关村创建了百度公司"}


我们通过如下的命令来进行搜索:



1.  GET alibaba_sparse/_search
2.  {
3.    "query": {
4.      "semantic": {
5.        "field": "inference_field",
6.        "query": "百度公司是哪年成立的?"
7.      }
8.    }
9.  }


上面搜索的结果为:

很显然,含有百度的文档排在第一的位置。这个就是我们所说的向量搜索。

在实际的很多例子中,我们有时想得到一个唯一的答案,甚至这个答案是推理出来的,而不原始的文档。这个时候我们就需要用到大模型,也就是使用 completion 这个推理端点。

我们首先来做如下的搜索:



1.  GET alibaba_sparse/_search
2.  {
3.    "query": {
4.      "semantic": {
5.        "field": "inference_field",
6.        "query": "阿里巴巴公司的法人是谁?"
7.      }
8.    }
9.  }


转存失败,建议直接上传图片文件

这次只有一个文档被列出来了。我们在下面使用 completion 端点:



1.  POST _inference/completion/alibabacloud_ai_search_completion
2.  {
3.    "input": "<|system|>
4.      你是一个知识渊博的人.</s>
5.      <|user|>
6.      CONTEXT:
7.      阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳

9.      QUESTION: 
10.      阿里巴巴公司的法人是谁?</s>
11.      <|assistant|>"
12.  }


在上面,我们把上面搜索的结果文档 “阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳” 作为 context 的一部分,并把搜索的问题也一并提交。我们使用 completion 端点 API 来查看结果:

转存失败,建议直接上传图片文件

上面显示的结果是 “阿里巴巴公司的法定代表人是蒋芳”。很显然这个和之前的直接使用 completion 而没有 context 的结果是完全不同的:



1.  POST _inference/completion/alibabacloud_ai_search_completion
2.  {
3.    "input": "阿里巴巴法定代表是谁?"
4.  }


转存失败,建议直接上传图片文件

我们可以这么理解,有了从 Elasticsearch 向量数据库(实时业务数据或私有数据)中搜索来的结果并提供给大模型,大模型可以根据这些上下文,得到更为贴近答案的搜索结果。这个在实际的使用中避免幻觉!

另外一个例子:



1.  POST _inference/completion/alibabacloud_ai_search_completion
2.  {
3.    "input": "<|system|>
4.      你是一个知识渊博的人.</s>
5.      <|user|>
6.      CONTEXT:
7.      阿里巴巴(中国)有限公司成立于2007年03月26日,法定代表人蒋芳

9.      QUESTION: 
10.      阿里巴巴(中国)有限公司是什么时候成立的?</s>
11.      <|assistant|>"
12.  }


转存失败,建议直接上传图片文件

有关如何构建提示(prompt),请参阅我之前的文章 “为生成式人工智能制作 prompt 三明治”。

好的,今天的分享就到这里。