使用 Elasticsearch 构建食谱搜索(一)
作者:来自 Elastic Andre Luiz

了解如何使用 Elasticsearch 构建基于语义搜索的食谱搜索。
简介
许多电子商务网站都希望增强其食谱搜索体验。正确使用语义搜索可以让客户根据更自然的查询(例如 “something for Valentine's Day - 情人节的礼物” 或 “Thanksgiving meals. - 感恩节大餐”)快速找到所需的食材。
在本文中,我们将演示如何使用 Elasticsearch 实现支持此类查询的语义搜索。我们将配置一个索引来存储超市的食材和产品目录,并演示如何使用此索引来改进食谱搜索。在整篇文章中,我们将解释如何创建此数据结构并应用自然语言处理技术来提供与客户意图一致的相关结果。
本文中介绍的所有代码都是用 Python 开发的,可在 GitHub 上找到。你可以访问存储库以查看源代码、根据需要进行调整并直接在你的开发环境中实施解决方案。
开始实施语义搜索
要开始实施语义搜索,我们首先需要定义自然语言模型。Elastic 提供自己的模型 ELSER,但也支持集成来自各种提供商(例如 Hugging Face)的 NLP 模型。这种灵活性使你可以选择最适合你需求的选项。
在本文中,我们将使用 ELSER,它降低了部署和管理 NLP 模型的复杂性。此外,Elastic 还提供 semantic_text 功能,大大简化了流程。使用 semantic_text,整个嵌入生成过程变得简单而自动化。你只需定义一个推理点并指定将接收索引映射中的嵌入的字段。在文档索引期间,将生成嵌入并自动与指定字段相关联。
设置步骤
以下是创建具有语义搜索支持的索引的步骤。按照这些说明,你将拥有一个配置好并准备好进行语义搜索的索引:
- 创建 inference point。
- 创建索引,将描述字段设置为 semantic_text,以便它可以接收嵌入。
- 将数据编入杂货目录索引,该索引将存储产品目录。此目录是从此处提供的数据集获得的。
语义搜索在杂货店中的应用
现在我们已经用杂货店产品数据填充了索引,我们正在测试和验证查询以使用语义搜索改进搜索结果。我们的目标是提供更智能的搜索体验,了解上下文和用户意图,提供更相关和准确的结果。
语义搜索解决的挑战
基于产品目录,让我们探索语义搜索如何通过解决传统词汇搜索经常遇到的词汇和上下文问题来改变杂货店的搜索体验。
1. 烹饪意图的解释
问题 01:客户可能会搜索 “seafood for grilling - 烧烤海鲜”,但词汇搜索系统可能无法完全理解查询背后的意图。它可能无法识别所有适合烧烤的海鲜产品,而只会返回产品标题中带有确切术语 “seafood - 海鲜” 或 “grill - 烧烤” 的产品。
首先,我们将执行词汇搜索并分析结果。然后,我们将使用语义搜索执行相同操作,比较相同搜索词的结果。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5,source_excludes="description_embedding",query={"multi_match": {"query": "seafood for grilling","fields": ["name","description"]}})
结果:
| Search Type | Name | Score |
|---|---|---|
| Lexical | Northwest Fish Alaskan Bairdi Snow Crab | 10.453125 |
| Lexical | Mr. Yoshida's, Sauce Original Gourmet | 7.2289705 |
| Lexical | Premium Seafood Variety Pack - 20 pcs | 7.1924105 |
| Lexical | American Red Snapper - Whole, Head-On, Cleaned | 6.998647 |
| Lexical | Lobster Claws & Arms, Sustainable Wild Caught | 6.438654 |
词汇搜索返回了一些适合烧烤的海鲜,例如 American Red Snapper 和 Northwest Fish Alaskan Bairdi Snow Crab。然而,词汇搜索返回的列表顶部有一些相关性较低的产品,例如 Mr. Yoshida sauce,它不是海鲜而是肉酱,这表明词汇算法很难完全理解 “for grilling - 烧烤” 的上下文。
语义搜索解决方案
我们使用将术语 “seafood” 与 “grilling” 等准备上下文相结合的查询来返回全面的选项列表,例如鱼片/fish fillets、虾/shrimp 和扇贝/scallops,这些都非常适合烧烤 - 即使 “grill - 烧烤” 或 “seafood - 海鲜” 字样没有直接出现在产品名称中。这可确保搜索结果与客户的意图更加一致。
查询语义搜索:
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "seafood for grilling"}})
| Search Type | Name | Score |
|---|---|---|
| Semantic | Whole Head On, Cleaned Branzino Fish | 16.175909 |
| Semantic | Alaska Black Cod (Sable Fish) | 15.855331 |
| Semantic | American Red Snapper - Whole, Head-On | 15.454779 |
| Semantic | Northwest Fish Alaskan Bairdi Snow Crab | 15.855331 |
| Semantic | American Red Snapper - Whole, Head-On | 15.3892355 |
语义搜索不仅返回与 “seafood - 海鲜”一词直接相关的产品,而且还理解 “grilling - 烧烤” 的上下文,显示适合烧烤的整条鱼和鱼片。这里的关键是结果的精确度,其中包括 Branzino 和阿拉斯加黑鳕鱼等整条鱼,这两种鱼都常用于烧烤。
问题 02:许多顾客在工作了一整天后会搜索快速简便的晚餐解决方案,使用 “easy weeknight meals” 等术语。传统的词汇搜索可能无法完全捕捉快餐的概念,通常只关注名称中包含 “easy - 简单”一词的产品。
正如我们在上一个问题中所做的那样,我们将首先执行词汇搜索。之后,我们将使用语义搜索应用解决方案。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5, source_excludes="description_embedding",query={"multi_match": {"query": "easy weeknight meals","fields": ["name","description"]}})
结果:
| Search Type | Name | Score |
|---|---|---|
| Lexical | Avery Easy Peel Address Labels, 4200-count | 8.017723 |
| Lexical | Omeals Self Heating Emergency/Portable Meals 32 | 6.592727 |
| Lexical | Coastal Seafood Yellowfin Tuna Cubed Poke | 5.836883 |
| Lexical | Hefty Super Weight 12 oz Foam | 5.8116536 |
| Lexical | Vanity Fair Everyday Napkin, 2-Ply, 110-count | 5.752989 |
词汇搜索返回的结果相关性要低得多,包括与餐食完全无关的商品,例如 Avery Easy Peel Address Labels 和 Vanity Fair Everyday Napkins。这些产品无法满足用户对快餐的需求。虽然词汇搜索确实返回了一款有用的产品(Omeals Self Heating Emergency Meals),但餐巾纸和标签等其他结果的描述中只匹配了 “easy” 或 “weeknight” 等字词,并没有真正满足用户对快餐解决方案的需求。
语义搜索解决方案
我们实施了一个查询,以了解快速简便的餐食背后的意图。它会关联可以快速准备的产品,例如预煮肉类、冷冻意大利面或餐食套装,即使它们的名称中没有明确包含 “easy” 一词。这种方法可确保客户找到最适合快速晚餐的选择,满足对便利的需求。
查询语义搜索
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "easy weeknight meals"}})
结果:
| Search Type | Name | Score |
|---|---|---|
| Semantic | Omeals Self Heating Emergency/Portable Meals 32 | 14.610006 |
| Semantic | Nissin, Cup Noodles, Shrimp, 2.5 oz | 13.751424 |
| Semantic | Namaste Gluten Free Waffle & Pancake Mix | 13.73376 |
| Semantic | Idaho Spuds, Golden Grill Hashbrown Potatoes | 12.549422 |
| Semantic | Nissin, Cup Noodles, Chicken, 24-Count | 12.034527 |
语义搜索返回的产品明显与快捷方便的餐食有关,例如方便面(Cup Noodles)、pre-cooked potatoes 和 pancake mixes,这些都是简单的平日晚餐的典型选择。这表明语义搜索可以掌握短语“简单的平日晚餐”背后的概念,捕捉用户寻找快捷方便餐食的意图。有趣的是,如果与上下文相关(例如,佐餐饮料),其他类别的产品(例如 “soda - 苏打水”)也可能包括在内。
2. 区域术语和词汇变化
问题:一位客户可能会搜索“soda - 苏打水”,而另一位客户可能会使用 “pop” 来搜索同一款产品。传统的词汇搜索无法识别这两个术语指的是同一款产品。
查询词汇搜索
response = client.search(index="grocery-catalog",size=5,source_excludes="description_embedding",query={"multi_match": {"query": "refreshing pop drink low sugar","fields": ["name","description"]}})
结果:
| Search Type | Name | Score |
|---|---|---|
| Lexical | Prime Hydration+ Sticks Electrolyte Drink Mix | 14.492869 |
| Lexical | Capri Sun, 100% Juice, Variety Pack | 12.340851 |
| Lexical | Joyburst Energy Drink, Frose Rose, 12 | 11.839179 |
| Lexical | Kellogg’s Pop-Tarts, Frosted Brown Sugar Cinnamon | 9.97788 |
| Lexical | Kind Mini Bars, Variety Pack, 0.7 | 9.336912 |
词汇搜索侧重于精确匹配单词。虽然它返回了 Prime Hydration 和 Capri Sun 等产品,但直接匹配 “pop” 一词也会导致不相关的结果,例如 Kellogg’s Pop-Tarts,它是一种零食而不是饮料。这凸显了当一个术语具有多重含义或可能含糊不清时,词汇搜索的效率会降低。
语义搜索解决方案
在语义查询中,我们可以克服词汇搜索无法解决的词汇变化问题。通过扩展搜索词,我们能够根据上下文含义获得结果,从而提供更相关、更全面的响应。
查询:
es_client.search(index="grocery-catalog-elser",size=size,source_excludes="description_embedding",query={"semantic": {"field": "description_embedding","query": "refreshing pop drink low sugar"}})
结果:
| Search Type | Name | Score |
|---|---|---|
| Semantic | Olipop 12 oz Prebiotics Soda Variety | 14.776867 |
| Semantic | Bai Antioxidant Cocofusion, Variety Pack, 18 | 14.663253 |
| Semantic | Monster Energy Drink, Zero Ultra, 24 | 14.486348 |
| Semantic | Joyburst Energy Variety, 12 fl oz | 14.007214 |
| Semantic | Joyburst Energy Drink, Frose Rose, 12 | 13.641038 |
语义搜索能够返回与 “pop” 作为 “soda” 同义词直接匹配的产品(例如 Olipop Prebiotics Soda),即使产品名称中未必出现 “pop” 这个确切的词。该搜索理解了用户的意图 —— 一种清爽、低糖的饮料 —— 并能够返回相关产品,包括益生元苏打(如 Olipop)和无糖能量饮料(如 Monster Energy Drink)等选项。
结论
事实证明,在杂货店环境中实施语义搜索对于理解“烧烤海鲜”和“简单的工作日晚餐”等复杂查询非常有效。这种方法使我们能够更准确地解释用户意图,返回高度相关的产品。
通过使用 Elasticsearch 并使用 ELSER 简化流程,我们能够快速高效地应用语义搜索,显著改善搜索结果并提供更灵活、更有针对性的购物体验。这不仅优化了搜索过程,还提高了向客户提供的结果的相关性。
参考资料 ELSER 模型:
Create inference API | Elasticsearch Guide [8.15] | Elastic
ELSER inference service | Elasticsearch Guide [8.15] | Elastic
语义文本:
Semantic text field type | Elasticsearch Guide [8.15] | Elastic
Semantic search | Elasticsearch Guide [8.15] | Elastic
数据集:
https://www.kaggle.com/datasets/bhavikjikadara/grocery-store-dataset?select=GroceryDataset.csv
语义搜索:
Semantic search | Elasticsearch Guide [8.15] | Elastic
Tutorial: semantic search with semantic_text | Elasticsearch Guide [8.15] | Elastic
准备好自己试试了吗?开始免费试用。
想要获得 Elastic 认证?查看下一次 Elasticsearch 工程师培训的时间!
原文:Building a recipe search with Elasticsearch - Search Labs
相关文章:
使用 Elasticsearch 构建食谱搜索(一)
作者:来自 Elastic Andre Luiz 了解如何使用 Elasticsearch 构建基于语义搜索的食谱搜索。 简介 许多电子商务网站都希望增强其食谱搜索体验。正确使用语义搜索可以让客户根据更自然的查询(例如 “something for Valentines Day - 情人节的礼物” 或 “…...
sealos部署K8s,安装docker时master节点突然NotReady
1、集群正常运行中,在集群master-1上安装了dockerharbor,却发现master-1节点NotReady,使用的网络插件为 Cilium #安装docker和harbor(docker运行正常) rootmaster-1:/etc/apt# apt install docker-ce5:19.03.15~3-0~u…...
使用vite+react+ts+Ant Design开发后台管理项目(五)
前言 本文将引导开发者从零基础开始,运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈,构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导,文章旨在为开发者揭示如何利用这些技术…...
Spring Boot实现多数据源连接和切换
文章目录 前言一、多数据源配置与切换方案二、实现步骤1. 创建多个 DataSource 配置类2. 创建 DataSource 配置类3. 创建动态数据源路由类4. 实现 DynamicDataSource 类5. 创建 DataSourceContextHolder 来存储当前的数据源标识6. AOP 方式切换数据源7. 自定义注解来指定数据源…...
发布 VectorTraits v3.0(支持 X86架构的Avx512系列指令集,支持 Wasm架构及PackedSimd指令集等)
文章目录 支持 X86架构的Avx512系列指令集支持Avx512时的输出信息 支持 Wasm架构及PackedSimd指令集支持PackedSimd时的输出信息VectorTraits.Benchmarks.Wasm 使用说明 新增了向量方法支持 .NET 8.0 新增的向量方法提供交织与解交织的向量方法YGroup3Unzip的范例代码 提供重新…...
详解如何创建SpringBoot项目
目录 点击New Project 选择依赖 简单使用SpringBoot 前面已经讲解了如何获取IDEA专业版,下面将以此为基础来讲解如何创建SpringBoot项目。 点击New Project 选择依赖 注意,在选择SpringBoot版本时,不要选择带SNAPSHOT的版本。 这样&#…...
IT架构管理
目录 总则 IT架构管理目的 明确组织与职责 IT架构管理旨在桥接技术实施与业务需求之间的鸿沟,通过深入理解业务战略和技术能力,推动技术创新以支持业务增长,实现技术投资的最大价值。 设定目标与范围 IT架构管理的首要目的是确立清晰的组织…...
Feign入门实践
引言 随着微服务架构的兴起,服务间的通信变得越来越频繁和复杂。为了简化服务之间的调用过程,提高开发效率和系统的可维护性,Spring Cloud 生态系统提供了多种解决方案,其中 OpenFeign 是一种声明式的 HTTP 客户端,它使…...
Leetcode 买卖股票的最佳时机 Ⅱ
使用贪心算法来解决此问题,通过在价格上涨的每一天买入并在第二天卖出的方式,累计所有上涨的利润,以实现最大收益。关键点是从第二天开始遍历,并且只要当前比前一天价格高,我们就在前一天买入然后第二天卖出去。下面是…...
书生大模型实战营-玩转HF/魔搭社区闯关任务
通过Github Codespace下载InternLM模型并运行 本篇博客是记录《书生大模型实战营第四期-玩转HF/魔搭/魔乐》章节的闯关任务从HF上下载模型文件,对实战营感兴趣的小伙伴也可以扫码报名哦。 一、通过模版创建Codespace环境 访问codespace 点击Jupyter Notebook 模版…...
混响(Reverb):原理、应用与发展趋势的深度解析
目录 引言1. 混响的基本原理2. 混响的应用3. 混响的技术实现4. 混响的未来发展趋势5. 总结 引言 混响(Reverb)是音频信号处理中的重要概念之一,在自然界和音频工程中都扮演着关键角色。从音乐制作到语音识别,从电影音效到虚拟现实…...
Java学习教程,从入门到精通,Java修饰符语法知识点及案例代码(23)
1.Java修饰符语法知识点及案例代码 Java修饰符用于改变类、方法、变量、接口等元素的行为和可见性。主要分为两大类:访问修饰符和非访问修饰符。 访问修饰符(Access Modifiers) public 提供最大的访问权限,任何类都可以访问。使…...
钉钉小程序使用getApp实现类型provide inject的功能 应用场景:解决页面同步子组件弹窗的滚动问题
前言:在开发钉钉小程序的时候 组件内部的弹窗滚动会带着视图同步滚动 所以需要在组件内部弹窗显示的时候禁用视图的scroll滚动 由于我组件封装的比较深 不可能逐级传递 dd也么有provide的语法 所以我使用的getApp 完成控制的效果 最终完美运行 觉得有帮助相互关注一下 后续会持…...
标准化 Git 提交信息的约定
在使用 Git 进行版本控制时,良好的提交信息可以帮助团队成员更好地理解每次提交的目的和影响。为了规范化提交信息,一些团队采用了特定的格式或约定,比如 Angular 团队提出的 Commit Message Conventions。这种规范有助于自动化工具的使用&am…...
React教程(详细版)
React教程(详细版) 1,简介 1.1 概念 react是一个渲染html界面的一个js库,类似于vue,但是更加灵活,写法也比较像原生js,之前我们写出一个完成的是分为html,js,css&…...
Perfect Forwarding(完美转发)
文章目录 1. 引用折叠2. 万能引用3. 完美转发3.1对比:std::move and std::forward比较 3.2使用时机3.3 返回值优化(RVO)两个前提条件注意事项 4. 完美转发失败情况完美转发失败五种情况 完美转发的实现要依赖于模版类型推导和引用折叠和万能引用。 1. 引…...
PHP露营地管理平台小程序系统源码
⛺️【露营新风尚】露营地管理平台系统全攻略⛺️ 🏕️一、露营热潮下的管理难题:如何高效运营露营地?🤔 随着露营文化的兴起,越来越多的人选择在大自然中享受宁静与自由。然而,露营地的管理却面临着诸多…...
速盾:vue的cdn是干嘛的?
CDN,即内容分发网络(Content Delivery Network),是一种将网站的静态资源分发到全球各个节点并缓存起来的技术。它可以帮助网站提供更快的加载速度,更好的用户体验,并且可以减轻源服务器的负载压力。 Vue.j…...
线性代数:Matrix2x2和Matrix3x3
今天整理自己的框架代码,将Matrix2x2和Matrix3x3给扩展了一下,发现网上unity数学计算相关挺少的,所以记录一下。 首先扩展Matrix2x2: using System.Collections; using System.Collections.Generic; using Unity.Mathemati…...
Windows 中 Electron 项目实现运行时权限提升以杀掉特定进程
#Windows 中 Electron 项目实现运行时权限提升以杀掉特定进程 一、引言 在 Windows 操作系统中,有时我们需要以管理员权限来执行某些操作,特别是当需要杀掉由管理员启动的进程时。Electron 是一个开源的框架,用于使用 JavaScript、HTML 和 C…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
