Kibana 控制台中提供语义、向量和混合搜索

news2025/1/18 13:05:35

作者:来自 Elastic Mark_Laney

想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗?那么,你不需要连接到某个第三方的大型语言模型(LLM)吗?不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索,以创建语义向量,并将其与常规搜索相结合,以获得更相关的搜索结果!

介绍

当谈到使用 AI 并将向量搜索应用于 Elastic 上的数据时,我看到很多教程和文章,它们可能变得相当复杂。我想表明,你可以利用今天正在运行的现有搜索,并通过语义和向量搜索来增强它们。你无需连接任何外部 LLM 或付费给任何大公司来处理你的数据。仅在 Elasticsearch 和 Kibana 中,你就可以下载 Elastic 的语义模型 ELSER,处理你的数据以添加描述向量,并增强你的搜索以探索改进。你不需要 LangChain、Python、chatGPT 或任何其他外部工具。

:目前 ELSER 只提供对英文的支持。它是一种稀疏向量的搜索方式。更多阅读,请参阅 “Elasticsearch:使用 ELSER 释放语义搜索的力量:Elastic Learned Sparse EncoderR”。

平台

我们将运行的搜索是在 Elasticsearch 和 Kibana 8.13.4 版本上完成的。你可以在任何你喜欢的平台上运行它们,无论是在本地还是在云端。

数据

我们将搜索的数据来自 Kaggle 的一组称为 “recipes” 的开放许可数据集。原始数据集可以从这里下载(在《使用 Elastic 的从业者向量搜索》第 173 页中讨论)。我下载了该文件并将其命名为 “allrecipes.csv”。

或者你可以从我的 GitHub 下载数据集。请打开该链接以在后续说明中下载其他文件。

删除重复数据

原始数据集中存在重复的条目。我编写了一个小型 Python 脚本来对它们进行重复数据删除。该脚本位于 GitHub 项目文件夹中,名为 dedupecsv.py。去重的结果文件叫做 allrecipes_dedupe.csv,它也在项目文件中。如果要自己运行 dedupecsv.py,则需要安装 python 库 pandas。 (例如 pip install pandas)。但是你不必执行这个重复数据删除,因为它已经完成,结果是 allrecipes_dedupe.csv。下载该文件。

索引数据

我能够使用 Filebeat 和(甚至更简单的)Kibana 中的文件上传器将数据导入 Elasticsearch 中的索引,最近使用的是 8.13.4 版本,但旧版本也可以使用。如果你使用 Filebeat 将 allrecipes_dedupe.csv 导入 Elasticsearch,则配置文件为 filebeat.yml ,并且副本位于项目文件夹中。我按照 “快速安装” 文档安装并使用 filebeat 作为 “自托管” 系统。如果你正在使用远程系统(如 Cloud 或 Strigo),请将 filebeat.yml 和 allrecipes_dedupe.csv 都 scp 到你的实例。

但使用文件上传器更容易,只需下载 allrecipes_dedupe.csv 并将其拖放到 Kibana 中。

使用任一方法,创建一个名为 “recipes” 的 Elasticsearch 索引。 Filebeat 将为你完成此操作。你在文件上传器中输入该名称。

Kibana

步骤 1:让我们验证食谱索引是否已成功导入 Elasticsearch。

在 Kibana 控制台(Kibana 主菜单 -> Management -> Dev Tools)中运行此命令:

GET _cat/indices?v&s=index

_cat API 提供行和列的输出。问号 (?v&s=index) 后面的字符是显示标题标签 (v) 和按 “index” 列排序 (&s=index) 的选项。

验证 recipes 索引的另一种方法是使用 _count API。

GET recipes/_count

步骤 2:下载 ELSER

Kibana UI 让我们可以在机器学习区域下载模型。转到主菜单-> Machine Learning。找到并点击 “Trained Models”。你应该会看到一个可用模型的简短列表。对于非英特尔环境,请下载 .elser_model_2。如果你的平台使用的是Intel x86 芯片,请下载专门准备的.elser_model_2_linux-x86_64。

步骤 3:启动模型

开始部署该模型进行推理。使用一个分配和四个线程。大多数情况下,分配会消耗一个核心,而线程就是该核心上的线程。下面的 API 调用为模型提供了一个名称 “elser_model”。

如果你运行的是 Intel x86 芯片:

POST _ml/trained_models/.elser_model_2_linux-x86_64/deployment/_start?deployment_id=elser_model&number_of_allocations=1&threads_per_allocation=4

否则:

POST _ml/trained_models/.elser_model_2/deployment/_start?deployment_id=elser_model&number_of_allocations=1&threads_per_allocation=4

如果需要启动和停止模型,可以执行以下操作:

POST _ml/trained_models/elser_model/deployment/_stop

如果管道正在调用模型(我们稍后会讲到):

POST _ml/trained_models/elser_model/deployment/_stop?force=true

确保模型处于启动状态:

GET _ml/trained_models/_stats/
GET _ml/trained_models/_stats?filter_path=trained_model_stats.deployment_stats.state

步骤 4:浏览食谱索引

运行这些命令来检查 recipes 索引的内容和属性。

检查索引中的某些文档:

GET recipes/_search

要查看字段及其数据类型:

GET recipes/_mapping

要查看索引的所有属性(映射、设置、别名),实际上更容易:

GET recipes

步骤 5:改进映射

如果我们运行这个:

GET recipes/_search?filter_path=hits.hits._source.id

请注意,所有 ID 都是小整数。然而,如果我们回过头来检查映射,我们会发现 ID 的数据类型可能是文本/关键字或长整型(取决于我们用来索引配方的工具)。

还要注意,summary 字段是数据类型 text,默认使用标准分析器。如果有英语分析器结果(提供词干结果),这将对我们的搜索很有用。这样,如果我们搜索“stewed” 西红柿的 summary,结果就会是 stewed、stew、stews、stewing等,这可能有助于更轻松地获得相关食谱。

此外,我们还需要创建一个字段来保存数据向量化的结果。稍后我们将配置一个摄取节点管道处理器来指示模型将结果写入名为 ml.tokens 的字段。正如这里所解释的,ELSER 模型结果应该存储为我们的向量嵌入的数据类型 “稀疏向量”。

考虑到这些改变,让我们创建一个具有所有改进的映射属性的不存在的索引。

PUT recipes_embeddings
{
  "mappings": {
    "properties": {
      "id": {
        "type": "short"
      },
      "group": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "ingredient": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "n_rater": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "n_reviewer": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "process": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "rating": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "summary": {
        "type": "text",
        "analyzer": "english",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "ml.tokens": {
        "type": "sparse_vector"
      }
    }
  }
}

步骤 6:其他文档修复

让我们再次检查一些有关食谱的文件。

GET recipes/_search
{
  "size": 2000,
  "_source": ["ingredient"]
}

如果你在控制台的右侧按 cntr+f find,你可能会注意到有些文档带有双引号或三引号。

在这里,我们创建一个摄取节点管道,将三重引号替换为单引号。
我们将我们的管道称为 “doublequotes”。

PUT _ingest/pipeline/doublequotes
{
  "processors": [
    {
      "gsub": {
        "field": "ingredient",
        "pattern": "\"(.*?)",
        "replacement": ""
      }
    }
  ]
}

为了测试我们的管道,我们可以使用_simulate API。

POST _ingest/pipeline/doublequotes/_simulate
{
  "docs": [
    {
      "_index": "recipes",
      "_id": "id",
      "_source": {
        "ingredient": """shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)""",
        "tags": 2342
      }
    }
  ]
}

步骤 7:带推理的管道

下面我们创建一个管道来清理引文并应用推理处理器。推理处理器是我们用来针对索引中的成分字段运行我们的模型(在本例中为 ELSER)的工具。回想一下,我们部署的名称是 else_model,我们在这里看到它被称为 model_id。我们将此管道称为 else_clean_recipes。

PUT _ingest/pipeline/elser_clean_recipes
{
  "processors": [
    {
      "pipeline": {
        "name": "doublequotes"
      },
      "inference": {
        "model_id": "elser_model",
        "target_field": "ml",
        "field_map": {
          "ingredient": "text_field"
        },
        "inference_config": {
          "text_expansion": {
            "results_field": "tokens"
          }
        }
      }
    }
  ]
}

请注意,模型默认对 “text_field” 字段进行向量化。在“field_map”行中,我们配置推理处理器以使用不同的字段(在本例中为成分)。

一定要测试。

POST _ingest/pipeline/elser_clean_recipes/_simulate
{
  "docs": [
    {
      "_index": "recipes",
      "_id": "id",
      "_source": {
        "ingredient": """prep: 20 mins,cook: 20 mins,total: 40 mins,Servings: 4,Yield: 4 servings","½ small onion, chopped + ½ tomato, chopped + 1 jalapeno pepper, seeded and minced + 1 sprig fresh cilantro, chopped + 6 eggs, beaten + 4 (10 inch) flour tortillas + 2 cups shredded Cheddar cheese + ¼ cup sour cream, for topping + ¼ cup guacamole, for topping""",
        "tags": 2342
      }
    },
     {
      "_index": "recipes",
      "_id": "id",
      "_source": {
        "ingredient":
    """"shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)"""
      }},
      {"_index": "recipes",
      "_id": "id",
      "_source": {  
        "ingredient": """shredded cheese, and even some cilantro for a great-tasting breakfast burrito that will keep your appetite curbed all day long.","prep: 15 mins,cook: 5 mins,total: 20 mins,Servings: 2,Yield: 2 burritos","2 (10 inch) flour tortillas + 1 tablespoon butter + 4 medium eggs + 1 cup shredded mild Cheddar cheese + 1 Hass avocado - peeled, pitted, and sliced + 1 small tomato, chopped + 1 small bunch fresh cilantro, chopped, or to taste (Optional) + 1 pinch salt and ground black pepper to taste + 1 dash hot sauce, or to taste (Optional)"""}}
  ]
}

步骤 8:通过管道处理数据

现在我们有了管道,是时候处理我们的索引了。我们将使用 _reindex API 将数据从 recipes 索引发送到 recipes_embeddings。在此过程中,数据将通过我们的管道来创建嵌入。

重新索引可能需要很长时间,因此我们在这里使用一个名为 wait_for_completion=false 的选项进行运行。

当我们运行命令时,它将生成一个 ID 号,我们可以使用它来检查进度。确保将此 ID 复制并粘贴到某处。

此外,重新索引正在使用选项......

requests_per_second=-1&timeout=60m

...分别以尽可能快的速度运行并且不会太快超时。

警告:可能需要大约 15-30 分钟

POST _reindex?wait_for_completion=false&requests_per_second=-1&timeout=60m
{
  "conflicts": "proceed", 
  "source": {
    "index": "recipes",
    "size": 500
  },
  "dest": {
    "index": "recipes_embeddings",
    "pipeline": "elser_clean_recipes"
  }
}

复制并使用任务编号来跟踪重新索引过程。

GET _tasks/< paste task number here >

例如,我复制并粘贴了这个ID:LAV3l8oZTmaR9p8VUVqO3g:373447

如果需要,你可以像这样删除 recipes_embeddings 索引。

DELETE recipes_embeddings

步骤 9:检查已处理的文件

至少一批文档完成后,检查结果。

GET _cat/indices?v&s=i

GET recipes_embeddings/_search

冗长的 ml.tokens 字段使得输出看起来不太好看。你可以像这样抑制它。

GET recipes_embeddings/_search
{ "_source": { "excludes": "ml"} }
GET recipes_embeddings/_count
4808 documents

我们可以运行这个聚合来找到我们可以查询的 “group” 中的所有不同值。

GET recipes_embeddings/_search?size=0
{
  "aggs": {
    "all the groups": {
      "terms": {
        "field": "group.keyword",
        "size": 200
      }
    }
  }
}

有多少个桶?

GET recipes_embeddings/_search
{
  "size": 0, 
  "aggs": {
    "how many buckets": {
      "cardinality": {
        "field": "group.keyword",
        "precision_threshold": 200
      }
    }
  }
}

我得到了 174 个不同的组。

为了隔离输出中的组以便我们可以在文档中看到它们,你可以运行以下命令:

GET recipes_embeddings/_search?size=1000&_source=group

搜索

最后,数据准备好了,我们可以在 recipes_embeddings 索引上执行搜索。让我们比较一下没有 ELSER 的运行结果和有 ELSER 的运行结果。

搜索 1:Old fashion(老式鸡尾酒)

首先,我们来寻找一种名为 Old Fashion 的鸡尾酒的配方。下面介绍如何进行此操作。

-- 老式波本鸡尾酒 --
1. 将一到两颗樱桃放入老式老式玻璃杯中,并用捣碎器轻轻捣碎。
2. 取橙皮并擦拭玻璃杯边缘内侧,然后将果皮放在樱桃上。
3. 加入冰块、黑麦威士忌、糖和苦味酒。
4. 搅拌均匀即可食用。

首先,没有 ELSER 的情况下:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml", "includes": ["name","group","summary","ingredient"]},
  "query": {
    "bool": {
      "should": [ { "wildcard": { "group": {"value": "drinks*" }}},
        {
          "multi_match": {
            "type": "phrase", 
            "query": "old fashion",
            "fields": [
              "summary",
              "name"]}},
        {
          "match": {
            "summary": "delicious sensational"
          }
        }
      ]
    }
  }
}

在你的控制台中运行它,你将看到热门点击中有一些非常糟糕的结果。
对我来说,它们都不是饮料(尽管我们搜索了饮料*组)。
我的许多搜索结果中都有诸如 “good old fashion meals and dishes...” 这样的短语,但这并不是我们想要的。

现在让我们用 ELSER 搜索...并看看出色的结果!

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml",
    "includes": [
      "name",
      "group",
      "summary",
      "ingredient"
    ]
  },
  "sub_searches": [
    {
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "group": {
                  "value": "drinks*"
                }
              }
            },
            {
              "multi_match": {
                "query": "old fashioned",
                "type": "phrase",
                "fields": [
                  "summary",
                  "name"
                ]
              }
            }
          ]
        }
      }
    },
    {
      "query": {
        "text_expansion": {
          "ml.tokens": {
            "model_id": "elser_model",
            "model_text": "old fashioned bourbon whiskey whisky drink"
          }
        }
      }
    }
  ],
  "rank": {
    "rrf": {
      "window_size": 500,
      "rank_constant": 60
    }
  }
}

请注意,所有这些都是成人饮料,并且有几种饮料的名称以 “Old Fashion” 开头。

搜索 2:Shrimp dishes

没有 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "group": {
              "value": "main*"
            }
          }
        },
        {
          "multi_match": {
            "type": "phrase", 
            "query": "tempura shrimp",
            "fields": [
              "ingredient",
              "name^2"
            ]
          }
        },
        {
          "match": {
            "summary": "tasty delightful"
          }
        }
      ]
    }
  }
}

前五名的结果相当糟糕:我得到了像 pork tenderloin、Spanish sauce、carrot salad 这样的食谱……甚至没有虾。

使用 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "sub_searches": [
    {
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "group": {
                  "value": "main*"
                }
              }
            },
            {
              "multi_match": {
                "query": "tempura shrimp",
                "type":"phrase",
                "fields": [
                  "ingredient",
                  "name^2"
                ]
              }
            }/*,
            {
              "match": {
                "summary": "tasty delightful"
              }
            }*/
          ]
        }
      }
    },
    {
      "query": {
        "text_expansion": {
          "ml.tokens": {
            "model_id": "elser_model",
            "model_text": "tempura shrimp"
          }
        }
      }
    }
  ],
  "rank": {
    "rrf": {
      "window_size": 500,
      "rank_constant": 60
    }
  }
}

排名前五的菜品要好得多:Shrimp with Pasta、Shrimp Scampis、Penne with Shrimp、Penne with Shrimp、Shrimp Quiche

请注意,Elasticsearch 如何通过语义搜索发现 shrimp 和 scampi 以及 prawns 等其他术语也具有相关性。

搜索 3:Spaghetti dishes

没有 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "group": {
              "value": "main*"
            }
          }
        },
        {
          "multi_match": {
            "type": "phrase", 
            "query": "Spaghetti Bolognese",
            "fields": [
              "ingredient",
              "name^2"
            ]
          }
        },
        {
          "match": {
            "summary": "tasty delightful"
          }
        }
      ]
    }
  }
}

前五名中又有糟糕的:pork tenderloin, Med. sauce, carrot salad, lime chicken……

我根本不喜欢意大利面。

使用 ELSER:

GET recipes_embeddings/_search?filter_path=hits.hits._source
{
  "_source": {
    "excludes": "ml"
  },
  "sub_searches": [
    {
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "group": {
                  "value": "main*"
                }
              }
            },
            {
              "multi_match": {
                "query": "Spaghetti Bolognese",
                "type":"phrase",
                "fields": [
                  "ingredient",
                  "name^2"
                ]
              }
            }/*,
            {
              "match": {
                "summary": "tasty delightful"
              }
            }*/
          ]
        }
      }
    },
    {
      "query": {
        "text_expansion": {
          "ml.tokens": {
            "model_id": "elser_model",
            "model_text": "main Spaghetti Bolognese"
          }
        }
      }
    }
  ],
  "rank": {
    "rrf": {
      "window_size": 500,
      "rank_constant": 60
    }
  }
}

改进了很多。很多食材都有意大利面或通心粉

再次排在最前面:Pennes, pastas, spaghettis。

搜索 4:巧克力

没有 ELSER:

GET recipes_embeddings/_search
{
  "_source": {"excludes": "ml"},
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "name": "dessert"
          }
        },
        {
          "match": {
            "ingredient": "chocolate"
          }
        },
        {
          "match": {
            "summary": "tasty delightful"
          }
        }
      ]
    }
  }
}

奶昔和薄饼……?

我找不到任何含巧克力的配料。

使用 ELSER:

GET recipes_embeddings/_search
{
  "_source": {"excludes": "ml"}, 
  "sub_searches": [
    {
      "query": {
        "bool": {
          "should": [
             {
              "match": {
                "name": "dessert"
              }
            },
            {
              "match": {
                "ingredient": "chocolate"
              }
            },
            {
              "match": {
                "summary": "tasty delightful"
              }
            }
          ]
        }
      }
    },
    {
      "query": {
        "text_expansion": {
          "ml.tokens": {
            "model_id": "elser_model",
            "model_text": "dessert chocolate"
          }
        }
      }
    }
  ],
  "rank": {
    "rrf": {
      "window_size": 50,
      "rank_constant": 20
    }
  }
}

Peppermint bark 是巧克力的一个晦涩术语。

Nanaimo bars 是一种巧克力顶上的饼干。我还看到hot chocolate, chocolate muffins, chocolate cake, Oreo truffles 和 cake balls,其中的配料包括巧克力。

我看到很多配料都含有巧克力。

我们再看一下我们可以查询的 “groups”。

GET recipes_embeddings/_search?size=0
{
  "aggs": {
    "all the groups": {
      "terms": {
        "field": "group.keyword",
        "size": 200
      }
    }
  }
}

everyday-cooking 有多少种菜谱?

GET recipes_embeddings/_count
{
  "query": {
    "wildcard": {
      "group.keyword": {
        "value": "everyday-cooking*"
      }
    }
  }
}

我得到 310。

鱼肉三明治 - Fish Sandwich

让我们在日常烹饪中寻找 “Fish Sandwich”。

没有 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "query": {
    "bool": {
      "should": [
        {
          "wildcard": {
            "group": {
              "value": "everyday-cooking*"
            }
          }
        },
        {
          "multi_match": {
            "type": "phrase", 
            "query": "fish sandwich",
            "fields": [
              "ingredient",
              "name^2"
            ]
          }
        }
      ]
    }
  }
}

没有!

哇,根本没有鱼肉三明治……?

使用 ELSER 添加嵌入搜索。

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "sub_searches": [
    {
      "query": {
        "bool": {
          "should": [
            {
              "wildcard": {
                "group": {
                  "value": "everyday-cooking*"
                }
              }
            },
            {
              "multi_match": {
                "query": "fish sandwich",
                "type":"phrase",
                "fields": [
                  "ingredient",
                  "name^2"
                ]
              }
            }
          ]
        }
      }
    },
    {
      "query": {
        "text_expansion": {
          "ml.tokens": {
            "model_id": "elser_model",
            "model_text": "fish sandwich"
          }
        }
      }
    }
  ],
  "rank": {
    "rrf": {
      "window_size": 500,
      "rank_constant": 60
    }
  }
}

在右侧搜索 “三明治”。

我看到 tuna patties, tuna salads - 很多鱼,很多都是三明治。

让我们看看“主菜”类别中有多少食谱?

让我们检查一下 “Main” 类别中有多少个食谱?

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml"
  },
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "group": "main*"
          }
        }
      ]
    }
  }
}

我得到了458。

里脊牛排 - Tenderloin Steak

请注意,在美国我们说 “tenderloins or tenderloin steaks”,但在法国它被称为 Chateaubriand。还请注意,“Chateaubriand” 不在任何食谱中。可以使用 multi_match 命令来搜索许多字段,如下所示:

GET recipes_embeddings/_search
{
  "query": {
    "multi_match": {
      "query": "Chateaubriand",
      "fields": ["ingredient","summary","name"]
    }
  }
}

零结果

不使用 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml", "includes": ["name","group","summary","ingredient"]},
  "query": {
    "bool": {
      "should": [ { "wildcard": { "group": {"value": "main*" }}},
        {
          "multi_match": {
            //"type": "phrase", 
            "query": "tenderloin steak Chateaubriand beef",
            "fields": [
              "ingredient",
              "name^2"
            ]
          }
        },
        {
          "match": {
            "summary": "delicious Chateaubriand"
          }
        },
        {
          "match": {
            "ingredient": "beef"
          }
        }
      ]
    }
  }
}

前十名的成绩相当糟糕。Salt and pepper fries, salt bread, Pork Tenderloin 等等。

使用 ELSER:

GET recipes_embeddings/_search
{
  "_source": {
    "excludes": "ml", "includes": ["name","group","summary","ingredient"]},
    "sub_searches": [
      {
        "query": {
          "bool": {
            "should": [
              {
                "wildcard": {"group": {"value": "main*"}}},
              {
                "multi_match": {
                  "query": "tenderloin steak Chateaubriand beef",
                  //"type":"phrase",
                  "fields": [
                    "ingredient",
                    "name^2"
                    ]
                }
              },
              {"match":{
                "ingredient":{
                  "query": "beef"
                }
              }}
              ]
          }
        }
      },
      {
        "query": {
          "text_expansion": {
            "ml.tokens": {
              "model_id": "elser_model",
              "model_text": "tenderloin steak Chateaubriand beef"
            }
          }
        }
      }
      ],
      "rank": {
        "rrf": {
          "window_size": 500,
          "rank_constant": 60
        }
      }
}

更多实际牛排。

恭喜!我们已经研究了许多示例,其中使用 ELSER 对数据进行向量化使我们能够进行语义搜索。我们将常规的、可能预先存在的术语搜索与向量搜索相结合,发现混合搜索结果通常比仅搜索术语本身更相关。

原文:Dec 13th, 2024: [EN] Semantic, Vector, and Hybrid Search all in Kibana Console - Advent Calendar - Discuss the Elastic Stack

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多种 Docker 镜像拉取解决方案与实践

最近国内 Docker 镜像拉取不太通畅&#xff0c;尝试了几种镜像拉取的方式&#xff0c;写篇博客分享一下。 原以为只是 docker hub 被毙了&#xff0c;上机器一操作&#xff0c;官方的下载地址也被毙了&#xff0c;真是从源头解决问题。 不过还好目前还有其他源能用&#xff0…

2025边缘计算新年沙龙成功举办,共话边缘AI未来

1月11日下午&#xff0c;北京市海淀区中关村创业大街热闹非凡&#xff0c;以“云边腾跃&#xff0c;蛇启新航”为主题的 2025边缘计算新年沙龙 盛大举行。本次活动汇聚了边缘计算、人工智能以及云边协同领域的顶尖专家、学者和从业者&#xff0c;共同探讨技术前沿与实际应用场景…

使用redis-cli命令实现redis crud操作

项目场景&#xff1a; 线上环境上redis中的key影响数据展示&#xff0c;需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤&#xff1a; 1、确定redis安装的服务器&#xff1b; 2、找到redis的安装目录下 ##找到redis安装目…

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍&#xff0c;无人会&#xff0c;解决法 想要下载软件通通失败了&#xff0c;解决方法当然是问AI&am…

【深度学习】神经网络之Softmax

Softmax 函数是神经网络中常用的一种激活函数&#xff0c;尤其在分类问题中广泛应用。它将一个实数向量转换为概率分布&#xff0c;使得每个输出值都位于 [0, 1] 之间&#xff0c;并且所有输出值的和为 1。这样&#xff0c;Softmax 可以用来表示各类别的预测概率。 Softmax 函…

python管理工具:conda部署+使用

python管理工具&#xff1a;conda部署使用 一、安装部署 1、 下载 - 官网下载&#xff1a; https://repo.anaconda.com/archive/index.html - wget方式&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…

unity——Preject3——开始界面拼面板

目录 1.创建panel&#xff0c;去掉panel自带的image&#xff0c;自己加一个image&#xff0c;使用锚点分配好 2.锚点&#xff08;快捷键点击后 ALTShift&#xff09; 锚点是什么&#xff1f; 锚点的实际例子 例子1&#xff1a;固定在父容器的中心 例子2&#xff1a;对齐到…

PyTorch使用教程(6)一文讲清楚torch.nn和torch.nn.functional的区别

torch.nn 和 torch.nn.functional 在 PyTorch 中都是用于构建神经网络的重要组件&#xff0c;但它们在设计理念、使用方式和功能上存在一些显著的区别。以下是关于这两个模块的详细区别&#xff1a; 1. 继承方式与结构 torch.nn torch.nn 中的模块大多数是通过继承 torch.nn…

传统以太网问题与VLAN技术详解

传统以太网的问题 广播域&#xff1a;在网络中能接收同一广播信息的所有设备&#xff08;计算机、交换机&#xff09;等的集合 说明&#xff1a;在一个广播域内&#xff0c;当一个设备发送广播帧时&#xff0c;该域内的所有设备都能接收到这个广播帧。工作原理&#xff1a;在以…

OpenAI Whisper:语音识别技术的革新者—深入架构与参数

当下语音识别技术正以前所未有的速度发展&#xff0c;极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者&#xff0c;它凭借其卓越的性能、广泛的适用性和创新的技术架构&#xff0c;正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…

WPS计算机二级•高效操作技巧

听说这里是目录哦 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9;横排转竖排&#x1f350;批量删除表格空白行&#x1f348;方法一方法二建辅助列找空值 能量站&#x1f61a; 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9; 选中单元格&#xff0c;单击右键➡️“设…

RabbitMQ实现延迟消息发送——实战篇

在项目中&#xff0c;我们经常需要使用消息队列来实现延迟任务&#xff0c;本篇文章就向各位介绍使用RabbitMQ如何实现延迟消息发送&#xff0c;由于是实战篇&#xff0c;所以不会讲太多理论的知识&#xff0c;还不太理解的可以先看看MQ的延迟消息的一个实现原理再来看这篇文章…

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者&#xff1a;Amy MiHyun Jang创建日期&#xff1a;2020/07/28最后修改时间&#xff1a;2024/02/12描述&#xff1a;TPU 上的医学图像分类。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…

1.17组会汇报

STRUC-BENCH: Are Large Language Models Good at Generating Complex Structured Tabular Data? STRUC-BENCH&#xff1a;大型语言模型擅长生成复杂的结构化表格数据吗&#xff1f;23年arXiv.org 1概括 这篇论文旨在评估大型语言模型&#xff08;LLMs&#xff09;在生成结构…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包&#xff0c;主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等&#xff0c;内容很多。我们基础学习的时候&#xff0c;只有关注张量的创建、序列化&#xff0c;随机数、张量的数学数学计算等常…

idea gradle compiler error: package xxx does not exist

idea 编译运行task时报项目内的包不存在&#xff0c;如果你试了网上的其它方法还不能解决&#xff0c;应该是你更新了新版idea&#xff0c;项目用的是旧版jdk&#xff0c;请在以下编译器设置中把项目JDK字节码版本设为8&#xff08;jdk1.8&#xff0c;我这里是17请自行选择&…

Nmap之企业漏洞扫描(Enterprise Vulnerability Scanning for Nmap)

简介 Namp是一个开源的网络连接端扫描软件&#xff0c;主要用于网络发现和安全审核。‌它可以帮助用户识别网络上的设备、分析它们的服务、检测操作系统类型&#xff0c;甚至发现潜在的安全漏洞。Nmap由Fyodor开发&#xff0c;最初是为了满足网络管理员的需求&#xff0c;但随…

RabbitMQ前置概念

文章目录 1.AMQP协议是什么&#xff1f;2.rabbitmq端口介绍3.消息队列的作用和使用场景4.rabbitmq工作原理5.整体架构核心概念6.使用7.消费者消息推送限制&#xff08;work模型&#xff09;8.fanout交换机9.Direct交换机10.Topic交换机&#xff08;推荐&#xff09;11.声明队列…

RabbitMQ---TTL与死信

&#xff08;一&#xff09;TTL 1.TTL概念 TTL又叫过期时间 RabbitMQ可以对队列和消息设置TTL&#xff0c;当消息到达过期时间还没有被消费时就会自动删除 注&#xff1a;这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身&#xff0c;不是说队列过期时间…