# 自然语言搜索
大型语言模型(LLMs)最强大的能力之一,就是能够将自然语言转化为结构化数据。在本指南中,我们将学习如何利用这一能力来理解用户的搜索查询,并将其转换为结构化的Typesense搜索查询。
# 使用场景
我们以一个公开的汽车数据集 (opens new window)为例。结合Google的Gemini (opens new window) LLM和Typesense,我们可以支持如下自然语言查询:
一辆本田或宝马,至少200马力,后轮驱动,价格2万到5万美元,必须是2014年以后的车
给我看看你们动力最强的车
高性能意大利车,700马力以上
我不会开手动挡
注意这些查询中有些包含多个条件,有些情况下关键词本身可能并不存在于数据集中。
以下是该数据集的一个示例记录供参考:
{
"city_mpg": 13,
"driven_wheels": "rear wheel drive",
"engine_cylinders": 8,
"engine_fuel_type": "premium unleaded (recommended)",
"engine_hp": 707,
"highway_mpg": 22,
"id": "1480",
"make": "Dodge",
"market_category": ["Factory Tuner", "High-Performance"],
"model": "Charger",
"msrp": 65945,
"number_of_doors": 4,
"popularity": 1851,
"transmission_type": "AUTOMATIC",
"vehicle_size": "Large",
"vehicle_style": "Sedan",
"year": 2017
}
# 数据流程
核心思路如下:
- 获取用户输入的自然语言查询
- 将其发送给LLM(大语言模型),附带具体指令要求将其转换为包含
filter_by
、sort_by
和q
搜索参数的Typesense查询 - 使用LLM返回的搜索参数在Typesense中执行查询并返回结果
我们本质上是在实现类似于"文本转SQL"的功能,只不过这里实现的是"文本转Typesense查询",执行查询并返回结果。
这个看似简单的概念能帮助构建强大的自然语言搜索体验。关键在于如何优化提示词,使其能稳定地将自然语言准确转换为合法的Typesense语法。
# 实时演示
以下视频展示了本指南将构建的效果:
你也可以在这里体验实时演示:https://natural-language-search-cars-genkit.typesense.org/ (opens new window)
接下来让我们看看如何端到端地构建这个应用。
# 项目设置
我们将使用 Next.js (opens new window) 和 Genkit (opens new window) 框架,后者能让我们在应用中轻松集成生成式 AI 功能。
请按照 Genkit 文档 (opens new window) 中的说明学习如何在 Next.js 应用中初始化 Genkit。
接下来,让我们安装 Typesense 客户端到应用中:
npm i typesense@next
我们将使用的数据集可以从 Github (opens new window) 下载。
# 初始化 Typesense 客户端
我们需要两个独立的 Typesense API 密钥:
- 一个仅用于前端搜索的 API 密钥
- 一个具有写入权限的后端 API 密钥
请参考 API 密钥 文档了解如何生成仅搜索 API 密钥。
如果您使用 Typesense Cloud,请在集群页面点击"Generate API key"按钮。这将为您提供一组可用的主机名和 API 密钥。
# 创建 Typesense 集合
我们将使用以下模式创建一个 Typesense Collection(集合),并将汽车数据集导入其中:
现在我们已经准备好将数据集索引到刚创建的集合中:
# 编写提示词
我们的目标是将自然语言查询(如'最新款福特车低于4万美元'
)转换为Typesense的查询格式:
{
"filter_by": "make:Ford && msrp:<40000",
"sort_by": "year:desc"
}
在Genkit中,模型输出模式使用Zod定义。
我们可以通过在generate()
中指定TypesenseQuerySchema
来使LLM输出符合我们的模式: