作者:来自 Elastic Michael Supangkat
了解如何在 Elastic Cloud 中,通过使用 LLM 生成的词汇,为搜索应用增强自动补全功能,实现更智能、更动态的搜索建议。
自动补全是搜索应用中的一项关键功能,它通过在用户输入时实时提供建议,显著提升用户体验。传统上,Elasticsearch 的自动补全功能是通过补全建议器(completion suggester)实现的,它依赖于预定义的词汇。这种方式需要人工整理建议词汇,且往往缺乏上下文的相关性。通过调用 OpenAI 的 completion 接口生成 LLM 词汇,我们可以构建一个更加智能、可扩展且自动化的自动补全功能。
用 LLM 强化你的搜索自动补全功能
在本文中,我们将探讨:
- 在 Elasticsearch 中实现自动补全的传统方法
- 如何通过集成 OpenAI 的 LLM 提升补全建议的质量
- 如何结合 Elastic Cloud 的 Ingest Pipeline 和 Inference Endpoint 实现可扩展的方案
Elasticsearch 传统的自动补全方式
在 Elasticsearch 中构建自动补全的常见做法是,在索引映射中定义一个补全字段(completion field)。这样 Elasticsearch 就可以基于预定义的词汇提供建议。
这种方法实现起来非常直接,尤其是当你的数据集相对静态,并且已经准备好了完整的建议词列表时。
实现步骤
- 创建一个包含 completion 字段的索引。
- 手动整理并维护建议词列表,并将其存储到索引中。
- 使用补全建议器(completion suggester)查询,获取相关建议。
示例:传统自动补全设置
首先,创建一个名为 products_test 的索引。在这个索引中,我们定义一个名为 suggest 的字段,类型为 completion,该字段专门用于快速自动补全建议。
PUT /products_test
{
"mappings": {
"properties": {
"suggest": { "type": "completion" }
}
}
}
向 products_test 索引中插入一个测试文档。suggest 字段存储多个补全建议词。
PUT /products_test/_doc/1
{
"suggest": ["MacBook Air M2", "Apple Laptop", "Lightweight Laptop"]
}
最后,我们使用 completion suggester 查询来搜索以 “MacB” 开头的建议词。
前缀 “MacB” 将匹配到 “MacBook Air M2”。
POST /products_test/_search
{
"suggest": {
"search-suggestion": {
"prefix": "MacB",
"completion": { "field": "suggest" }
}
}
}
suggest
部分包含匹配到的建议词。
options
包含一个匹配建议的数组,其中 "text": "MacBook Air M2"
是最优先的建议结果。
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"suggest": {
"search-suggestion": [
{
"text": "MacB",
"offset": 0,
"length": 4,
"options": [
{
"text": "MacBook Air M2",
"_index": "products_test",
"_id": "1",
"_score": 1,
"_source": {
"suggest": [
"MacBook Air M2",
"Apple Laptop",
"Lightweight Laptop"
]
}
}
]
}
]
}
}
虽然这种方法有效,但它依赖于手动整理和不断更新建议词汇,且无法动态适应新产品或描述的变化。
更多有个 autocomplete 的文章,请在 “Elastic:开发者上手指南” 里查找 “autocomplete"。
用 OpenAI LLM 增强自动补全功能
在某些场景中,数据集会频繁变化,这就需要你不断更新有效的建议词列表。当出现新的产品、名称或术语时,你必须手动将它们添加到建议列表中。
这正是 LLM 发挥作用的地方 —— 它可以基于真实世界的知识和最新数据,动态生成相关补全词汇。
通过调用 OpenAI 的 completion 接口,我们可以基于产品名称和描述动态生成自动补全建议。这带来的好处包括:
- 自动生成同义词和相关术语
- 基于产品描述的上下文感知建议
- 无需手动维护词表,系统更加可扩展
基于 LLM 的自动补全实现步骤
- 使用 OpenAI 的 completion API 创建一个推理端点(Inference Endpoint)。
- 配置一个 Elasticsearch ingest pipeline,在 pipeline 中使用脚本处理器(script processor),调用 OpenAI 接口并使用预定义 prompt 获取补全建议。
- 将生成的建议词存储到带有 completion 字段的 Elasticsearch 索引中。
- 使用搜索请求获取动态补全结果。
以上所有步骤都可以通过在 Kibana Dev Tools 中逐步复制粘贴 API 请求完成。
在本示例中,我们使用的是 gpt-4o-mini 模型。你需要提前获取你的 OpenAI API 密钥。登录你的 OpenAI 账号,然后访问 https://platform.openai.com/api-keys,创建一个新的密钥或使用已有密钥。
创建推理端点(Inference Endpoint)
首先,我们需要创建一个推理端点。
这个端点让我们可以通过 API 与机器学习模型(这里是 OpenAI)无缝交互,同时还能保持在 Elastic 的界面中进行操作。
PUT _inference/completion/openai-completion
{
"service": "openai",
"service_settings": {
"api_key": "<insert_your_api_key>",
"model_id": "gpt-4o-mini"
}
}
设置 Elasticsearch Ingest Pipeline
通过设置一个 ingest pipeline,我们可以在数据索引时进行处理。在这个案例中,pipeline 被命名为 autocomplete-LLM-pipeline,并包含以下内容:
- 脚本处理器(script processor):定义我们发送给 OpenAI 的 prompt,以获取建议词列表。产品名称和产品描述作为动态值包含在 prompt 中。
- 推理处理器(inference processor):引用我们之前创建的 OpenAI 推理端点。该处理器接收来自脚本处理器的 prompt 作为输入,将其发送到 LLM 模型,并将结果存储在一个名为 results 的输出字段中。
- 分割处理器(split processor):将 LLM 输出的文本结果分割成逗号分隔的数组,以适应 suggest 类型字段的格式。
- 2 个删除处理器(remove processors):在填充 suggest 字段后,删除 prompt 和 results 字段。
PUT _ingest/pipeline/autocomplete-LLM-pipeline
{
"processors": [
{
"script": {
"source": "\n ctx.prompt = 'Based on the following product name and product description, create relevant autocomplete suggestion terms from the following product, including the exact product name itself as the first term, synonyms of the product category, and keywords which might commonly be used when searching the following product:' + '\\\\n Product Name:\\\\n' + ctx.ProductName + '\\\\nProduct Description:\\\\n' + ctx.Description + '\\\\nJust include the suggestion terms in the response, as an array encapsulated in double quotes and separated by commas without any prefix or numbering'\n "
}
},
{
"inference": {
"model_id": "openai-completion",
"input_output": {
"input_field": "prompt",
"output_field": "results"
}
}
},
{
"split": {
"field": "results",
"separator": ",",
"target_field": "suggest"
}
},
{
"remove": {
"field": "prompt"
}
},
{
"remove": {
"field": "results"
}
}
]
}
为了能让让大家把上面的 prompt 看得更清楚,我们在下面重新粘贴:
ctx.prompt = 'Based on the following product name and product description, create relevant autocomplete suggestion terms from the following product, including the exact product name itself as the first term, synonyms of the product category, and keywords which might commonly be used when searching the following product:' + '\\\\n Product Name:\\\\n' + ctx.ProductName + '\\\\nProduct Description:\\\\n' + ctx.Description + '\\\\nJust include the suggestion terms in the response, as an array encapsulated in double quotes and separated by commas without any prefix or numbering'\n
更多有关在 ingest pipeline 里调用 LLM 的示例,我们可以阅读 “分面搜索:利用人工智能改善搜索范围和结果”。
索引示例文档
在这个示例中,我们使用 documents API 通过开发工具手动将文档索引到一个临时索引中,名为 'products'。
需要注意的是,这并不是我们最终用于自动补全的索引。
PUT products/_doc/1
{
"ProductName": "MacBook Air M2",
"Description": "The MacBook Air M2 is a powerful, ultra-portable laptop designed to deliver exceptional performance, all while maintaining an ultra-slim profile. Powered by Apple’s latest M2 chip, this lightweight machine is perfect for both work and play, combining top-tier performance with impressive battery life"
}
创建带有 Completion 类型映射的索引
现在,我们将创建实际用于自动补全的索引,该索引包含一个名为 suggest 的 completion 类型字段。
PUT products_with_suggestion
{
"mappings": {
"properties": {
"suggest": { "type": "completion" }
}
}
}
通过 Ingest Pipeline 重新索引文档到指定索引
在这一步中,我们将之前创建的 products 索引中的数据重新索引到实际的自动补全索引 products_with_suggestion,并通过 autocomplete-LLM-pipeline 进行处理。
该 pipeline 将处理来自原始索引的示例文档,并将结果填充到目标索引中的 suggest 自动补全字段。
POST _reindex?slices=auto&wait_for_completion=false
{
"source": {
"index": "products"
},
"dest": {
"index": "products_with_suggestion",
"pipeline": "autocomplete-LLM-pipeline"
}
}
展示自动补全建议
如下所示,新的索引 products_with_suggestion 现在包含一个名为 suggest 的新字段,该字段包含由 OpenAI LLM 生成的词汇或同义词数组。
你可以运行以下请求来检查:
GET products_with_suggestion/_search
结果:
{
"hits": [
{
"ProductName": "MacBook Air M2",
"Description": "The MacBook Air M2 is a powerful, ultra-portable laptop designed to deliver exceptional performance, all while maintaining an ultra-slim profile. Powered by Apple’s latest M2 chip, this lightweight machine is perfect for both work and play, combining top-tier performance with impressive battery life",
"suggest": [
"MacBook Air M2",
"ultra-portable laptop",
"lightweight laptop",
"performance laptop",
"Apple laptop",
"M2 chip laptop",
"thin laptop",
"best laptop for work",
"laptop with long battery life",
"powerful lightweight laptop",
"Apple MacBook",
"MacBook Air",
"laptop for students",
"portable computer",
"laptop for professionals"
]
},
{
"ProductName": "DKNY Unisex Black & Grey Printed Medium Trolley Bag",
"Description": "Black and grey printed medium trolley bag, secured with a TSA lockOne handle on the top and one on the side, has a trolley with a retractable handle on the top and four corner mounted inline skate wheelsOne main zip compartment, zip lining, two compression straps with click clasps, one zip compartment on the flap with three zip pocketsWarranty: 5 yearsWarranty provided by Brand Owner / Manufacturer",
"suggest": [
"DKNY Unisex Black & Grey Printed Medium Trolley Bag",
"medium trolley bag",
"travel bag",
"luggage",
"roller bag",
"printed suitcase",
"black and grey suitcase",
"trolley luggage",
"travel trolley",
"carry-on trolley",
"retractable handle bag",
"inline skate wheels bag",
"TSA lock luggage",
"zip compartment suitcase",
"compression straps bag",
"soft sided luggage",
"durable travel bag",
"wheeled duffel bag",
"luggage with warranty",
"brand name luggage"
]
}
]
}
请注意,即使使用相同的 prompt,LLM 生成的词汇也不总是相同的。你可以检查生成的词汇,看看它们是否适合你的搜索用例。如果不符合需求,你可以选择修改脚本处理器中的 prompt,以获得更可预测和一致的建议词汇。
测试自动补全搜索
现在,我们可以使用 completion suggester 查询来测试自动补全功能。下面的示例还包括一个 fuzzy 参数,通过处理搜索查询中的小拼写错误来提升用户体验。你可以在开发工具中执行以下查询,并查看建议结果。
POST /products_with_suggestion/_search
{
"suggest": {
"search-suggestion": {
"prefix": "lugg",
"completion": {
"field": "suggest",
"fuzzy": { "fuzziness": 1 }
}
}
}
}
为了可视化自动补全结果,我实现了一个简单的搜索栏,它通过客户端在 Elastic Cloud 中针对自动补全索引执行查询。随着用户输入,搜索会基于 LLM 生成的建议列表中的词汇返回结果。
通过 OpenAI 推理集成进行扩展
通过在 Elastic Cloud 中将 OpenAI 的 completion API 作为推理端点,我们可以高效地扩展这个解决方案:
- 推理端点 允许自动化和可扩展的 LLM 建议生成,而无需手动创建和维护建议词汇列表。
- Ingest Pipeline 确保在索引过程中实时丰富数据。
- 脚本处理器(Script Processor)在 ingest pipeline 中允许轻松编辑 prompt,以便在需要时更具体地定制建议列表的内容。
- Pipeline 执行 还可以直接配置为索引模板,以进一步实现自动化。这使得随着新产品的添加,建议列表可以动态生成。
在成本效率方面,模型只在索引过程中调用,这意味着它的使用随着处理的文档数量而扩展,而不是搜索量。因此,预计用户增长或搜索活动增加时,这种方法比在搜索时运行模型节省更多的成本。
结论
传统的自动补全依赖于手动定义的词汇,这既有限制又劳动密集。通过利用 OpenAI 生成的 LLM 建议,我们可以选择自动化并增强自动补全功能,提升搜索相关性和用户体验。此外,使用 Elastic 的 ingest pipeline 和推理端点集成,确保了自动化和可扩展的自动补全系统。
总的来说,如果你的搜索用例需要一套非常具体的建议,且是从一个经过精心维护和整理的列表中提取的,按照本文第一部分的描述,通过 API 批量导入建议词汇仍然是一个很好的高效选择。如果管理和更新建议列表是一个痛点,那么基于 LLM 的补全系统通过自动生成上下文相关的建议,省去了手动输入的麻烦。
Elasticsearch 提供了与行业领先的生成 AI 工具和供应商的本地集成。可以查看我们的网络研讨会,了解如何超越 RAG 基础,或构建适合生产的 Elastic 向量数据库应用。
为了为你的用例构建最佳的搜索解决方案,立即开始免费云试用,或尝试在本地机器上运行 Elastic。
原文:How to build autocomplete feature on search application automatically using LLM generated terms - Elasticsearch Labs