如何自动化同义词并使用我们的 Synonyms API 进行上传

作者:来自 Elastic Andre Luiz

了解如何使用 LLM 来自动识别和生成同义词, 使术语可以通过程序方式加载到 Elasticsearch 同义词 API 中。

提高搜索结果的质量对于提供高效的用户体验至关重要。优化搜索的一种方法是通过同义词自动扩展查询词。这样可以更广泛地解释查询内容,覆盖语言变体,从而改进结果匹配。

本博客探讨了如何利用 大语言模型(LLMs) 自动识别和生成同义词,使这些术语可以通过程序方式加载到 Elasticsearch 的 synonym API 中。

何时使用同义词?

使用 同义词 相较于 向量搜索 是一种更快速且更具成本效益的解决方案。它的实现更简单,因为它不需要深入了解 embeddings 或复杂的向量摄取过程。

此外,同义词的 资源消耗更低 ,因为向量搜索需要更大的存储空间和内存来进行 embedding 索引和检索。

另一个重要方面是 搜索的区域化 。通过 同义词 ,可以根据本地语言和习惯调整术语,这在 embeddings 可能无法匹配地区表达或特定国家术语的情况下非常有用。例如,一些单词或缩写在不同地区可能有不同的含义,但本地用户通常会将它们视为同义词:

  • 巴西 ,"abacaxi" 和 "ananás" 都指 菠萝(pineapple),但在东北部,第二个词更常见。

  • 在巴西东南部,常见的 "pão francês"(法式面包)在东北部可能被称为 "pão careca"。

这种 区域化 的差异使得 同义词 在搜索优化中发挥关键作用。

如何使用 LLMs 生成同义词?

为了自动获取同义词, 你可以使用 LLMs, 这些模型可以分析术语的上下文并建议合适的变体。 这种方法可以动态扩展同义词, 确保更广泛和更精准的搜索, 而无需依赖固定的词典。

在本示例中, 我们将使用 LLM 来为 电商产品 生成同义词。 许多搜索由于查询词的不同变体而返回较少甚至没有结果。 通过 同义词 , 我们可以解决这个问题。 例如, 搜索 "smartphone" 时, 结果可以涵盖不同型号的手机, 确保用户能够找到他们需要的产品。

先决条件

在开始之前, 需要设置环境 并定义所需的依赖项 。 我们将使用 Elastic 提供的解决方案 在 Docker 中本地运行 Elasticsearch 和 Kibana。 代码将使用 Python v3.9.6 编写,并需要以下依赖项:

ini 复制代码
`pip install openai==1.59.8 elasticsearch==8.15.1`AI写代码

创建产品索引

首先, 我们将创建一个不支持同义词的产品索引。 这将使我们能够验证查询, 然后将其与包含同义词的索引进行比较。

要创建索引, 我们使用以下命令在 Kibana DevTools 中批量加载产品数据集:

json 复制代码
`

1.  POST _bulk
2.  {"index": {"_index": "products", "_id": 10001}}
3.  {"category": "Electronics", "name": "iPhone 14 Pro"}
4.  {"index": {"_index": "products", "_id": 10007}}
5.  {"category": "Electronics", "name": "MacBook Pro 16-inch"}
6.  {"index": {"_index": "products", "_id": 10013}}
7.  {"category": "Electronics", "name": "Samsung Galaxy Tab S8"}
8.  {"index": {"_index": "products", "_id": 10037}}
9.  {"category": "Electronics", "name": "Apple Watch Series 8"}
10.  {"index": {"_index": "products", "_id": 10049}}
11.  {"category": "Electronics", "name": "Kindle Paperwhite"}
12.  {"index": {"_index": "products", "_id": 10067}}
13.  {"category": "Electronics", "name": "Samsung QLED 4K TV"}
14.  {"index": {"_index": "products", "_id": 10073}}
15.  {"category": "Electronics", "name": "HP Spectre x360 Laptop"}
16.  {"index": {"_index": "products", "_id": 10079}}
17.  {"category": "Electronics", "name": "Apple AirPods Pro"}
18.  {"index": {"_index": "products", "_id": 10115}}
19.  {"category": "Electronics", "name": "Amazon Echo Show 10"}
20.  {"index": {"_index": "products", "_id": 10121}}
21.  {"category": "Electronics", "name": "Apple iPad Air"}
22.  {"index": {"_index": "products", "_id": 10127}}
23.  {"category": "Electronics", "name": "Apple AirPods Max"}
24.  {"index": {"_index": "products", "_id": 10151}}
25.  {"category": "Electronics", "name": "Sony WH-1000XM4 Headphones"}
26.  {"index": {"_index": "products", "_id": 10157}}
27.  {"category": "Electronics", "name": "Google Pixel 6 Pro"}
28.  {"index": {"_index": "products", "_id": 10163}}
29.  {"category": "Electronics", "name": "Apple MacBook Air"}
30.  {"index": {"_index": "products", "_id": 10181}}
31.  {"category": "Electronics", "name": "Google Pixelbook Go"}
32.  {"index": {"_index": "products", "_id": 10187}}
33.  {"category": "Electronics", "name": "Sonos Beam Soundbar"}
34.  {"index": {"_index": "products", "_id": 10199}}
35.  {"category": "Electronics", "name": "Apple TV 4K"}
36.  {"index": {"_index": "products", "_id": 10205}}
37.  {"category": "Electronics", "name": "Samsung Galaxy Watch 4"}
38.  {"index": {"_index": "products", "_id": 10211}}
39.  {"category": "Electronics", "name": "Apple MacBook Pro 16-inch"}
40.  {"index": {"_index": "products", "_id": 10223}}
41.  {"category": "Electronics", "name": "Amazon Echo Dot (4th Gen)"}

`AI写代码

使用 LLM 生成同义词

在此步骤中, 我们将使用 LLM 动态生成同义词。 为此, 我们将集成 OpenAI API , 定义合适的模型和提示词。 LLM 将接收产品类别和名称, 确保生成的同义词在上下文中具有相关性。

python 复制代码
`

1.  import json
2.  import logging

4.  from openai import OpenAI

6.  def call_gpt(prompt, model):
7.      try:
8.          logging.info("generate synonyms by llm...")
9.          response = client.chat.completions.create(
10.              model=model,
11.              messages=[{"role": "user", "content": prompt}],
12.              temperature=0.7,
13.              max_tokens=1000
14.          )
15.          content = response.choices[0].message.content.strip()
16.          return content
17.      except Exception as e:
18.          logging.error(f"Failed to use model: {e}")
19.          return None

21.  def generate_synonyms(category, products):
22.     synonyms = {}

24.     for product in products:
25.         prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
26.         prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
27.         prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
28.         prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
29.         prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

31.         response = call_gpt(prompt, "gpt-4o")
32.         synonyms[product] = response

34.     return synonyms

`AI写代码

从创建的产品索引中, 我们将检索 "Electronics"(电子产品) 类别中的所有商品, 并将它们的名称发送到 LLM。 预期的输出将类似于:

json 复制代码
`

1.  {
2.    "iPhone 14 Pro": ["iPhone", "smartphone", "mobile", "handset"],
3.    "MacBook Pro 16-inch": ["MacBook", "Laptop", "Notebook", "Ultrabook"],
4.    "Samsung Galaxy Tab S8": ["Tab", "Tablet", "Slate", "Pad"],
5.    "Bose QuietComfort 35 Headphones": ["Headphones", "earphones", "earbuds", "headset"]
6.  }

`AI写代码

使用生成的同义词, 我们可以通过 Synonyms API 将它们注册到 Elasticsearch 中。

使用 Synonyms API 管理同义词

Synonyms API 提供了一种有效的方式, 让我们直接在系统中管理同义词集合。 每个同义词集合由同义词规则组成, 在这些规则中,一组词在搜索中被视为等同。

创建同义词集合的示例

markdown 复制代码
`

1.  PUT _synonyms/my-synonyms-set
2.  {
3.    "synonyms_set": [
4.      {
5.        "id": "rule-1",
6.        "synonyms": "hello, hi"
7.      },
8.      {
9.        "synonyms": "bye, goodbye"
10.      }
11.    ]
12.  }

`AI写代码

​这将创建一个名为 "my-synonyms-set" 的同义词集,其中将 "hello" 和" hi" 视为同义词,"bye" 和 "goodbye" 也视为同义词。

实现产品目录的同义词创建

以下是负责构建同义词集并将其插入 Elasticsearch 的方法。 同义词规则是基于 LLM 提供的同义词映射生成的。 每条规则都有一个 ID,对应于产品名称的 slug 格式,以及由 LLM 计算得出的同义词列表。

python 复制代码
`

1.  import json
2.  import logging

4.  from elasticsearch import Elasticsearch
5.  from slugify import slugify

7.  es = Elasticsearch(
8.      "http://localhost:9200",
9.      api_key="your_api_key"
10.  )

12.  def mount_synonyms(results):
13.     synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
14.                     results.items()]

16.     try:
17.         response = es.synonyms.put_synonym(id="products-synonyms-set",
18.                                                   synonyms_set=synonyms_set)

20.         logging.info(json.dumps(response.body, indent=4))
21.         return response.body
22.     except Exception as e:
23.         logging.error(f"Error create synonyms: {str(e)}")
24.         return None

`AI写代码

以下是创建同义词集的请求负载:

json 复制代码
`

1.  {
2.     "synonyms_set":[
3.        {
4.           "id": "iphone-14-pro",
5.           "synonyms": "iPhone, smartphone, mobile, handset"
6.        },
7.        {
8.           "id": "macbook-pro-16-inch",
9.           "synonyms": "MacBook, Laptop, Notebook, Computer"
10.        },
11.        {
12.           "id": "samsung-galaxy-tab-s8",
13.           "synonyms": "Tablet, Slate, Pad, Device"
14.        },
15.        {
16.           "id": "garmin-forerunner-945",
17.           "synonyms": "Forerunner, smartwatch, fitness watch, GPS watch"
18.        },
19.        {
20.           "id": "bose-quietcomfort-35-headphones",
21.           "synonyms": "Headphones, Earphones, Headset, Cans"
22.        }
23.     ]
24.  }

`AI写代码

在集群中创建了同义词集后,我们可以进入下一步,即使用定义的同义词集创建一个带有同义词支持的新索引。

下面是使用 LLM 生成的同义词和通过 Synonyms API 定义的同义词集创建的完整 Python 代码:

ini 复制代码
`

1.  import json
2.  import logging

4.  from elasticsearch import Elasticsearch
5.  from openai import OpenAI
6.  from slugify import slugify

8.  logging.basicConfig(level=logging.INFO)

10.  client = OpenAI(
11.     api_key="your-key",
12.  )

14.  es = Elasticsearch(
15.      "http://localhost:9200",
16.      api_key="your_api_key"
17.  )

20.  def call_gpt(prompt, model):
21.     try:
22.         logging.info("generate synonyms by llm...")
23.         response = client.chat.completions.create(
24.             model=model,
25.             messages=[{"role": "user", "content": prompt}],
26.             temperature=0.7,
27.             max_tokens=1000
28.         )
29.         content = response.choices[0].message.content.strip()
30.         return content
31.     except Exception as e:
32.         logging.error(f"Failed to use model: {e}")
33.         return None

36.  def generate_synonyms(category, products):
37.     synonyms = {}

39.     for product in products:
40.         prompt = f"You are an expert in generating synonyms for products. Based on the category and product name provided, generate synonyms or related terms. Follow these rules:\n"
41.         prompt += "1. **Format**: The first word should be the main item (part of the product name, excluding the brand), followed by up to 3 synonyms separated by commas.\n"
42.         prompt += "2. **Exclude the brand**: Do not include the brand name in the synonyms.\n"
43.         prompt += "3. **Maximum synonyms**: Generate a maximum of 3 synonyms per product.\n\n"
44.         prompt += f"The category is: **{category}**, and the product is: **{product}**. Return only the synonyms in the requested format, without additional explanations."

46.         response = call_gpt(prompt, "gpt-4o")
47.         synonyms[product] = response

49.     return synonyms

52.  def get_products(category):
53.     query = {
54.         "size": 50,
55.         "_source": ["name"],
56.         "query": {
57.             "bool": {
58.                 "filter": [
59.                     {
60.                         "term": {
61.                             "category.keyword": category
62.                         }
63.                     }
64.                 ]
65.             }
66.         }
67.     }
68.     response = es.search(index="products", body=query)

70.     if response["hits"]["total"]["value"] > 0:
71.         product_names = [hit["_source"]["name"] for hit in response["hits"]["hits"]]
72.         return product_names
73.     else:
74.         return []

77.  def mount_synonyms(results):
78.     synonyms_set = [{"id": slugify(product), "synonyms": synonyms} for product, synonyms in
79.                     results.items()]

81.     try:
82.         es_client = get_client_es()
83.         response = es_client.synonyms.put_synonym(id="products-synonyms-set",
84.                                                   synonyms_set=synonyms_set)

86.         logging.info(json.dumps(response.body, indent=4))
87.         return response.body
88.     except Exception as e:
89.         logging.error(f"Erro update synonyms: {str(e)}")
90.         return None

93.  if __name__ == '__main__':
94.     category = "Electronics"
95.     products = get_products("Electronics")
96.     llm_synonyms = generate_synonyms(category, products)
97.     mount_synonyms(llm_synonyms)

`AI写代码

创建支持同义词的索引

将创建一个新索引,其中所有来自 products 索引的数据将被重新索引。该索引将使用 synonyms_filter ,该过滤器应用之前创建的 products-synonyms-set

下面是配置为使用同义词的索引映射:

json 复制代码
`

1.  PUT products_02
2.  {
3.    "settings": {
4.      "analysis": {
5.        "filter": {
6.          "synonyms_filter": {
7.            "type": "synonym",
8.            "synonyms_set": "products-synonyms-set",
9.            "updateable": true
10.          }
11.        },
12.        "analyzer": {
13.          "synonyms_analyzer": {
14.            "type": "custom",
15.            "tokenizer": "standard",
16.            "filter": [
17.              "lowercase",
18.              "synonyms_filter"
19.            ]
20.          }
21.        }
22.      }
23.    },
24.    "mappings": {
25.      "properties": {
26.        "ID": {
27.          "type": "long"
28.        },
29.        "category": {
30.          "type": "keyword"
31.        },
32.        "name": {
33.          "type": "text",
34.          "analyzer": "standard",
35.          "search_analyzer": "synonyms_analyzer"
36.        }
37.      }
38.    }
39.  }

`AI写代码

重新索引 products 索引

现在,我们将使用 Reindex API 将数据从 products 索引迁移到新的 products_02 索引,该索引包括同义词支持。以下代码在 Kibana DevTools 中执行:

json 复制代码
`

1.  POST _reindex
2.  {
3.    "source": {
4.      "index": "products"
5.    },
6.    "dest": {
7.      "index": "products_02"
8.    }
9.  }

`AI写代码

迁移后,products_02 索引将被填充并准备好验证使用配置的同义词集的搜索。

使用同义词验证搜索

让我们比较两个索引之间的搜索结果。我们将在两个索引上执行相同的查询,并验证是否使用同义词来检索结果。

在 products 索引中搜索(没有同义词)

我们将使用 Kibana 执行搜索并分析结果。在 Analytics > Discovery 菜单中,我们将创建一个数据视图来可视化我们创建的索引中的数据。

Discovery 中,点击 Data View 并定义名称和索引模式。对于 "products" 索引,我们将使用 "products" 模式。然后,我们将重复这个过程,为 "products_02" 索引创建一个新的数据视图,使用 "products_02" 模式。

配置好数据视图后,我们可以返回 Analytics > Discovery 并开始验证。

在这里,选择 DataView products 并搜索术语 "tablet" 后,我们没有得到任何结果,尽管我们知道有像 "Kindle Paperwhite""Apple iPad Air" 这样的产品。

products_02 索引中搜索(支持同义词)

在支持同义词的 "products_synonyms" 数据视图上执行相同的查询时,产品成功地被检索到了。这证明了配置的同义词集正常工作,确保搜索词的不同变体返回预期的结果。

我们可以通过直接在 Kibana DevTools 中运行相同的查询来实现相同的结果。只需使用 Elasticsearch Search API 搜索 products_02 索引:

结论

在 Elasticsearch 中实现同义词提高了产品目录搜索的准确性和覆盖面。关键的区别在于使用了 LLM,它自动且上下文相关地生成同义词,消除了预定义列表的需求。该模型分析了产品名称和类别,确保了与电子商务相关的同义词。

此外,Synonyms API 简化了词典管理,允许动态修改同义词集。通过这种方法,搜索变得更加灵活,能够适应不同的用户查询模式。

这一过程可以通过新数据和模型调整不断改进,确保越来越高效的研究体验。

参考资料

在本地运行 Elasticsearch
Run Elasticsearch locally | Elasticsearch Guide [8.17] | Elastic

Synonyms API
Synonyms APIs | Elasticsearch Guide [8.17] | Elastic

想获得 Elastic 认证?了解下次 Elasticsearch 工程师培训的时间!

Elasticsearch 拥有丰富的新功能,帮助你为使用案例构建最佳搜索解决方案。深入了解我们的示例笔记本,了解更多内容,开始免费云试用,或立即在本地机器上尝试 Elastic。

原文:How to automate synonyms and upload using our Synonyms API - Elasticsearch Labs

相关推荐
Code额4 小时前
Elasticsearch 的搜索功能
elasticsearch·微服务
lilye665 小时前
程序化广告行业(44/89):岗位职责与RTB竞价逻辑深度解析
大数据·elasticsearch·flask·memcache
致良知云5 小时前
elasticsearch-7.17.16阿里云部署
elasticsearch·阿里云·jenkins
被放养的研究生16 小时前
Git和GitCode使用(从Git安装到上传项目一条龙)
git·elasticsearch·gitcode
java技术小馆1 天前
ES的文档更新机制
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客1 天前
如何自动化同义词并使用我们的 Synonyms API 进行上传
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·自动化
Elasticsearch1 天前
将代理连接到 Elasticsearch 使用模型上下文协议
elasticsearch
烛.照1031 天前
SpringBoot整合Easy-Es
java·spring boot·elasticsearch
2401_897930062 天前
docker下安装 es 设置账号密码
elasticsearch·docker·jenkins