
🛠️ 弥合语义和生成搜索!
当你想找到缓解头痛的药方,却发现自己患有可怕疾病时,是不是很烦恼?你在谷歌上搜索你的症状,在仔细研究了前几个搜索结果后,毫无疑问,你可能将在几个小时内死于可怕的疾病。剧透警告,几乎从来都不是这样。这种现象被称为谷歌医生,为了拯救你于压力之中,我们想帮助你探索其他人可能为他们的病情找到的帮助。
在这里试用实时演示✨

Healthsearch 是一个技术演示,充当概念验证。Healthsearch 中显示的结果不应被视为健康建议,也不是此演示的目的。搜索结果基于查询与用户撰写的评论之间的语义相似性。
想象一下,你可以输入 我需要更好地睡眠,并立即获得一份相关的补充剂列表,其中其他用户撰写评论称它帮助他们更好地睡眠。或者你正在处理持续的关节疼痛,并正在寻找一种天然补充剂来缓解不适。
我们很高兴发布我们最新的开源演示 Healthsearch。此演示解码用户撰写的补充剂评论,并对其执行语义和生成搜索,根据评论检索与特定健康影响最相关的产品,并利用大型语言模型生成产品和评论摘要。该演示可以理解自然语言查询,并直接从查询的上下文中推断所有搜索过滤器。
在这篇博文中,我将带你快速了解 Healthsearch 项目及其惊人的功能。我们还将了解实现和我在开发过程中面临的挑战。
我们提供所有源代码在 GitHub 上,供你发现和用于自己的项目。
💡 以用户为中心的设计,实现直观的搜索
你可能首先注意到的左侧的搜索栏。它不仅仅是一个简单的搜索工具。它被设计为接受任何自然语言查询,以帮助你找到针对特定健康影响的补充剂。例如,查询范围可以从 对关节疼痛有益 和 改善肌肉再生 到 更好的睡眠。但这里有一个转折点 - 与典型的搜索体验不同,你不会在特定字段上找到任何过滤器、排序或结果限制。
这就是魔力开始的地方!
我们使用大型语言模型 (LLM),例如 GPT4,将你的日常语言查询转换为结构化的查询格式,称为 GraphQL 查询。
你可能想知道,GraphQL 查询是什么? 简单来说,它是一种强大的查询语言,它允许我们只请求我们需要的特定信息,而不是获得预定义的集合信息。
令人兴奋的是,我们可以直接从查询的上下文中提取有关过滤器、排序和限制的信息。因此,无论你是在询问 适合发光肌肤的前 10 款产品、来自特定品牌的产品睡眠 或 评价最高的牙痛产品,我们的演示都可以解释这些查询并返回适当的 GraphQL 查询。
对我来说,很高兴看到我们成功实现了这个功能,尽管它并不完美,还需要一些改进,但我认为这个功能具有令人兴奋的潜力来改善整体搜索体验。这是一个从自然语言到 GraphQL 的示例转换。
自然语言查询
GraphQL
{
Get{
Product(
nearText: {concepts: ["sleep"]}
where: {
path: ["brand"],
operator: Equal,
valueString: "Now Foods"
}
) {
name
brand
ingredients
reviews
image
rating
description
summary
effects
_additional {
id
distance
}
}
}
}
现在,让我们深入了解幕后发生的事情。收到自然语言查询后,我们使用 GPT4 Chat Completion API 生成 GraphQL 查询。Chat Completion 功能就像与 AI 进行对话。你提供一系列消息作为输入,模型生成相关的响应作为输出。
我们向模型提供使用 Weaviate 的 nearText 功能、排序机制、过滤器和限制的示例,以便它生成与 Weaviate 兼容的查询。

🔮 应用于你自己的用例!
此功能不限于健康补充剂,可以适应任何其他领域。鼓励使用其他 LLM 提供商和开源替代方案,这是我们未来想要尝试的事情!要开始,欢迎你探索我们 GitHub 仓库中的所有源代码,以了解它是如何逐行实现的。只需克隆项目并阅读文档即可设置演示!(如果你熟悉 Docker,只需一条命令即可设置所有内容 😈)
准确性 使用 LLM 输出时,一致性无法保证,因此很难保证一定的查询质量。你可以尝试不同的模型,这可能会带来更好的结果。但是,为了能够比较 LLM 之间的结果,你需要根据搜索指标(如 归一化折损累积增益 (NDCG))来评估你的搜索结果。我渴望尝试 OpenAI 的新函数调用功能。
限制 成功生成查询的关键部分是提供正确的文档并优化提示。但是,为了减少提示工程的开销,我认为微调 LLM 或使用可以检索特定文档作为上下文的系统也可能是一种更好的方法来解决这个问题。
性能 使用 GPT-4 给出良好的结果,但速度非常慢。我希望技术能够改进,并且出现更快更好的替代方案。为了在生产中使用此功能,我建议选择更快的 LLM 并权衡一些质量。
🔎 使用语义搜索解码评论
Healthsearch 如何确定哪些补充剂适合特定的健康影响?它依赖于用户评论中的语义搜索的力量。当你正在寻找对 关节疼痛有益 的产品时,Healthsearch 会扫描用户评论,查找讨论减轻关节疼痛或类似情况的产品。然后,结果会根据各自的产品进行汇总。正如我之前提到的,所有结果都完全基于用户撰写的评论的内容。
语义搜索的优势在这种用例中真正闪耀,因为评论通常是非结构化的,并且可以用多种方式表达。例如,短语 对关节疼痛有益、对关节疼痛有帮助 和 改善关节炎,措辞可能不同,但具有相同的语义含义。捕获这些变化对于这个特定用例非常重要,并且也普遍适用于涉及用户评论的其他用例。
但是,我们如何使用 Weaviate 实现这一点?这个过程非常简单。我们创建了嵌入了评论、摘要和其他元数据的 产品 对象,以启用语义搜索。为了优化性能,我们使用 gpt-3.5-turbo 模型向量化特定的字段,并排除不需要向量化的字段。我们选择该模型是因为它比 GPT4 更快,但你可以使用任何其他嵌入模型(Cohere、HuggingFace 等)。
产品模式
class_obj = {
"class": "Product",
"description": "Supplement products",
"properties": [
{
"dataType": ["text"],
"description": "The name of the product",
"name": "name",
"moduleConfig": {
"text2vec-openai": {
"skip": True,
"vectorizePropertyName": False,
}
},
},
{
"dataType": ["text"],
"description": "The brand of the product",
"name": "brand",
"moduleConfig": {
"text2vec-openai": {
"skip": True,
"vectorizePropertyName": False,
}
},
},
{
"dataType": ["text"],
"description": "The ingredients contained in the product.",
"name": "ingredients",
"moduleConfig": {
"text2vec-openai": {
"skip": False,
"vectorizePropertyName": True,
}
},
},
{
"dataType": ["text[]"],
"description": "Reviews about the product",
"name": "reviews",
"moduleConfig": {
"text2vec-openai": {
"skip": True,
"vectorizePropertyName": False,
}
},
},
{
"dataType": ["text"],
"description": "Image URL of the product",
"name": "image",
"moduleConfig": {
"text2vec-openai": {
"skip": True,
"vectorizePropertyName": False,
}
},
},
{
"dataType": ["number"],
"description": "The Rating of the product",
"name": "rating",
"moduleConfig": {
"text2vec-openai": {
"skip": True,
"vectorizePropertyName": False,
}
},
},
{
"dataType": ["text"],
"description": "The description of the product",
"name": "description",
"moduleConfig": {
"text2vec-openai": {
"skip": False,
"vectorizePropertyName": True,
}
},
},
{
"dataType": ["text"],
"description": "The summary of the reviews",
"name": "summary",
"moduleConfig": {
"text2vec-openai": {
"skip": False,
"vectorizePropertyName": True,
}
},
},
{
"dataType": ["text"],
"description": "The health effects of the product",
"name": "effects",
"moduleConfig": {
"text2vec-openai": {
"skip": False,
"vectorizePropertyName": True,
}
},
},
],
"moduleConfig": {"generative-openai": {"model": "gpt-3.5-turbo"}},
"vectorizer": "text2vec-openai",
}
为了让你更清楚地了解,我们使用 Python 字典在 Weaviate 数据库中定义一个新的类(类似于蓝图)。该类包括产品名称、品牌、评论、评分等字段。指定每个字段的数据类型,可以是文本、图像、数字等,并添加简短的描述和字段名称。一些字段被配置为向量化,这意味着它们的语义内容将被合并到数据库中索引的整体向量中。不贡献语义丰富度的字段(如评分或图像 URL)被排除,以保持嵌入质量。
在使用语义搜索用户评论时,需要考虑的一个关键因素是评论的真实性和相关性。在将数据集输入数据库进行语义搜索之前,确保数据集不包含虚假或不相关的评论至关重要。
在开发 Healthsearch 时,我利用了我本科论文中的一个模型,一个名为 Healthsea 的 spaCy 模型。该模型可以快速分析评论并过滤关注健康影响的评论,从而提高我们语义搜索的输入质量。虽然我没有为 Healthsearch 包含特定的虚假评论过滤器,但我已经在我的论文中解决了这个问题。对于那些有兴趣探索如何处理虚假评论的人,我在这篇文章中更深入地探讨了这个话题:Healthsea。
💥 利用生成式搜索增强搜索结果
在将查询翻译成 GraphQL 并检索最具语义相关性的产品后,我们通过一项名为 生成式搜索 的功能来增强我们的演示。本质上,我们检查前五个结果并使用 LLM 生成产品摘要。这个简洁的摘要提供了产品简要概述,突出了它们的优缺点并提供了有价值的见解。更棒的是什么?每个摘要都是围绕您的查询定制的,确保每次搜索都是独一无二且有趣的。
这大大增强了用户体验,您可以快速了解产品信息,只需阅读摘要即可。它简化了复杂的信息并有助于快速决策。这种方法用途广泛,除了创建摘要之外,还可以应用于许多其他用例。
有关与 Weaviate 结合的生成式反馈循环的更详细介绍,请参阅 Connor 的 精彩博文。
在 Weaviate 中实现生成式搜索涉及使用 generate 模块 来定义提示和将用作上下文的字段。对于每个生成的查询,都会使用 generate 模块创建另一个查询。这样做是为了确保仅考虑前 5 个产品(以管理上下文长度),并且这些查询将并行执行。结果是包含生成摘要的前 5 个产品的列表。
GraphQL 与 generate 模块
{
Get {
Product(
limit: 5
nearText: {concepts: ["Helpful", "joint pain"]}
) {
ingredients
description
summary
_additional {
generate(
groupedResult: {
task: "Summarize products based on this query: Helpful for joint pain"
}
) {
groupedResult
error
}
id
distance
}
}
}
}
}
虽然生成式搜索具有巨大的潜力,但它也伴随着自身的挑战
质量控制
由于每个生成的摘要都取决于用户查询,因此确保这些文本的质量可能是一个重大障碍。这里的挑战是:我们如何始终如一地生成准确、相关且有用的摘要,并根据每个唯一查询对其进行评估?
性能
由于我们使用的是 GPT4(再次),处理需要时间,这使得搜索体验有些耗费精力。如果处理时间对您的用例至关重要,我建议寻找其他更快的方法。
🔥 介绍语义缓存
生成查询及其摘要,尤其是在使用 GPT4 模型时,可能是一个耗时的过程。因此,缓存以前的结果对于提高系统效率至关重要。缓存还有助于应对 LLM API 中断,为您的项目创建新的依赖层。但是,如果我们能更进一步呢?如果我们利用 Weaviate 作为缓存并利用其语义搜索功能呢?
“对关节疼痛有帮助”与“对关节疼痛好”
如果仅依赖字符串匹配,这两个查询将是不同的。但是,当我们深入研究它们的语义上下文时,它们传达了相同的含义。那么,为什么不嵌入查询,以便在查询的语义含义与以前的查询密切一致时返回缓存结果呢?
这种方法,我称之为语义缓存,具有优势,因为它使我们能够从生成的結果中提取比传统字符串匹配更多的信息。它是一种简单但强大的解决方案,可以提高搜索过程的效率。

💚 开源是王道
该项目的存储库完全开源,让您可以访问每一行代码,包括前端和后端。我们还提供我们的补充数据集的摘录,使您能够在个人设备上运行整个演示。该演示可以作为起点和显示您自己数据的模板。
这篇博文向您介绍了 Healthsearch,一个很棒的演示,它允许您使用基于特定健康影响的自然语言查询来探索健康补充剂。我们研究了语义和生成式搜索,将搜索指令翻译成 GraphQL,并使用 Weaviate 作为 语义缓存。我希望这篇博文能激励您,并且您会发现所呈现的一些功能对您自己的项目有用!
感谢您抽出时间阅读这篇博文。我们邀请您查看我们的存储库并深入了解语义和生成式搜索的迷人世界! 💚

准备开始构建了吗?
请查看 快速入门教程,或使用 Weaviate Cloud (WCD) 的免费试用版构建令人惊叹的应用程序。