人工智能的兴起引发了基于LLM的应用开发浪潮,向量数据库通过高效处理大规模结构化和非结构化数据发挥着关键作用。其中,基于ClickHouse构建的SQL向量数据库MyScaleDB已成为开发者的首选。MyScaleDB与SQL完全兼容,使开发者能够以最小的学习曲线构建生成式AI应用,与低代码平台配合使用,进一步降低了开发门槛。
最近,MyScaleDB与领先的低代码平台DronaHQ集成,提供了更加易于使用的开发体验。本文将演示如何使用MyScaleDB强大的向量搜索在DronaHQ上创建智能餐厅推荐系统,通过个性化建议提升用户体验。
# 什么是 DronaHQ
DronaHQ是一个强大的低代码应用开发平台,它将各种技能水平的开发者统一起来,可以构建从简单的微工具到强大的企业级应用,如仪表板、数据库GUI、管理面板、审批应用、客户支持工具等,以帮助改善业务运营。该平台使开发者能够轻松地在各种数据库上构建多屏应用,并集成第三方API,并利用强大的安全功能、丰富的UI元素和灵活的共享选项进行部署后的开发。DronaHQ最大限度地减少了开发应用程序所需的工程时间,而无需处理后端的麻烦。虽然该平台的关键是拖放功能,但开发者可以自由编写代码和使用库函数来设计UI和自定义,并编写逻辑和调试。
借助DronaHQ的低代码平台,您可以创建集成了向量搜索等高级数据功能的全面应用。通过本文,您将学习以下内容:
- 了解向量搜索及其应用的基础知识。
- 在MyScaleDB中准备和管理数据,以实现更有效的搜索。
- 无缝集成MyScaleDB和DronaHQ,构建一个具有位置感知的餐厅推荐应用。
- 在DronaHQ平台内快速创建和部署利用高级搜索功能的强大应用。
# 什么是向量搜索
向量搜索 (opens new window)是一种先进的技术,将数据转化为向量,放置在多维空间中,其中每个向量表示数据的关键特征。使用余弦相似度,这些向量根据它们在空间中的接近程度进行比较。这有助于确定两个数据点在概念上或上下文上有多相似,即使它们不共享完全相同的词语。这种方法超越了传统的关键字搜索,它只匹配特定的关键字。向量搜索在您希望找到语义上相似的项目时特别有用,即使它们并不完全相同。
在餐厅推荐系统中,向量搜索可以通过将氛围、用户评价和用餐体验等各种因素转化为向量表示来分析和比较。这使得系统能够识别在整体用餐体验方面相似的餐厅,而不仅仅是匹配特定的标准,如菜系或价格范围。
# 在MyScaleDB中准备数据
在本文中,我们将使用MyScaleDB (opens new window),这是一个基于ClickHouse的开源高性能SQL向量数据库。它旨在提供具有熟悉的SQL查询语言的高级向量搜索功能。MyScaleDB建立在ClickHouse (opens new window)之上,可以高效地管理结构化和向量化数据,使其成为大规模AI应用的理想选择。
选择MyScaleDB作为该项目的主要原因之一是它的多尺度树图(MSTG) (opens new window)索引算法。该算法在成本和性能方面优于专门的向量数据库,提供高速向量操作和高效的数据存储。最重要的是,MyScaleDB允许新用户免费保存多达500万个向量,因此我们不需要为这个MVP应用支付任何费用。
# 创建MyScaleDB集群
要在DronaHQ应用中使用MyScaleDB,首先需要在MyScaleDB云上创建一个用于数据存储的集群。为此,请访问MyScaleDB控制台 (opens new window),注册、登录,并点击右上角的“新建集群”按钮创建您的MyScale集群。
在输入集群名称后,点击“下一步”按钮,等待集群启动完成。
\
创建集群后,点击集群右侧的“操作”按钮。然后从弹出列表中选择“连接详细信息”。保存“Python”选项卡中的主机/端口/用户名/密码信息。这些信息将用于访问和保存数据到MyScaleDB集群。
现在,我们已经完成了MyScaleDB配置的设置,接下来是准备和保存数据到这个新创建的集群。
# 准备和保存数据
我们使用经过特定定制以满足我们要求的合成生成数据,该数据是使用大型语言模型(LLM)创建的。您可以通过相应的GitHub存储库 (opens new window)访问此数据集。
# 安装依赖项
首先,我们需要安装必要的库。取消下面一行的注释并运行它以安装所需的软件包。如果这些库已经安装在您的系统上,您可以跳过此步骤。
# pip install sentence-transformers clickhouse_connect
# 加载数据
首先,您需要将从GitHub获取的数据加载到本地目录中。确保正确指定文件的路径。以下是如何加载数据的示例:
import pandas as pd
# 从CSV文件加载数据
df_restaurants = pd.read_csv("restaurants.csv")
df_users = pd.read_csv("users.csv")
df_reviews = pd.read_csv("reviews.csv")
这里,我们有三个CSV文件:
restaurants.csv
:包含餐厅的详细信息,如名称、评分、菜系、平均价格和位置。reviews.csv
:包含用户评论,指定哪个用户对哪个餐厅给出了什么评分。users.csv
:存储用户偏好,包括偏好的菜系、平均评分和平均消费。
# 加载嵌入模型
接下来,我们将使用Huggingface
的嵌入模型为我们的文本数据生成嵌入。我们使用的模型是免费的,名为sentence-transformers/all-MiniLM-L6-v2
。
import torch
from transformers import AutoTokenizer, AutoModel
# 初始化嵌入模型的分词器和模型
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
def get_embeddings(texts: list) -> list:
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt", max_length=512)
with torch.no_grad():
outputs = model(**inputs)
embeddings = outputs.last_hidden_state.mean(dim=1)
return embeddings.numpy().tolist()
get_embeddings
方法将接受一个字符串列表,并返回它们的嵌入。
# 生成嵌入
现在,让我们为我们的数据中的特定字段生成嵌入,例如餐厅的菜系类型、用户的偏好菜系和每个餐厅的评论。这些嵌入将在后面执行相似性搜索时起到关键作用。
# 为菜系类型和用户偏好生成嵌入
df_restaurants["cuisine_embeddings"] = get_embeddings(df_restaurants["cuisine"].tolist())
df_users["cuisine_preference_embeddings"] = get_embeddings(df_users["cuisine_preference"].tolist())
# 为评论生成嵌入
df_reviews["review_embeddings"] = get_embeddings(df_reviews["review"].tolist())
# 与MyScaleDB建立连接
要连接到您的MyScaleDB集群,请使用您在集群创建过程中复制的连接详细信息。这将允许您建立与MyScaleDB实例的连接。
import clickhouse_connect
# 连接到MyScaleDB
client = clickhouse_connect.get_client(
host='your_host_name_here',
port=443,
username='your_username_here',
password='your_password_here'
)
# 创建表
下一步是在MyScaleDB集群中创建表,您可以在这些表中存储数据,根据应用程序的需求,为用户、餐厅和评论创建表。
# 创建用户表
client.command("""
CREATE TABLE default.users (
userId Int64,
cuisine_preference String,
rating_preference Float32,
price_range Int64,
latitude Float32,
longitude Float32,
cuisine_preference_embeddings Array(Float32),
CONSTRAINT check_data_length CHECK length(cuisine_preference_embeddings) = 384
) ENGINE = MergeTree()
ORDER BY userId
""")
# 创建评论表
client.command("""
CREATE TABLE default.reviews (
userId Int64,
restaurantId Int64,
rating Float32,
review String,
review_embeddings Array(Float32),
CONSTRAINT check_data_length CHECK length(review_embeddings) = 384
) ENGINE = MergeTree()
ORDER BY userId
""")
# 创建餐厅表
client.command("""
CREATE TABLE default.restaurants (
restaurantId Int64,
name String,
cuisine String,
rating Float32,
price_range Int64,
latitude Float32,
longitude Float32,
cuisine_embeddings Array(Float32),
CONSTRAINT check_data_length CHECK length(cuisine_embeddings) = 384
) ENGINE = MergeTree()
ORDER BY restaurantId
""")
# 将数据插入表中
创建表后,您现在可以使用插入方法将数据插入这些表中。
# 将数据插入用户表
client.insert("default.users", df_users.to_records(index=False).tolist(), column_names=df_users.columns.tolist())
# 将数据插入评论表
client.insert("default.reviews", df_reviews.to_records(index=False).tolist(), column_names=df_reviews.columns.tolist())
# 将数据插入餐厅表
client.insert("default.restaurants", df_restaurants.to_records(index=False).tolist(), column_names=df_restaurants.columns.tolist())
# 创建MSTG索引
最后,为了在数据中进行高效的搜索,为每个表创建一个MSTG索引。
# 为用户创建MSTG索引
client.command("""
ALTER TABLE default.users
ADD VECTOR INDEX user_index cuisine_preference_embeddings
TYPE MSTG
""")
# 为餐厅创建MSTG索引
client.command("""
ALTER TABLE default.restaurants
ADD VECTOR INDEX restaurant_index cuisine_embeddings
TYPE MSTG
""")
# 为评论创建MSTG索引
client.command("""
ALTER TABLE default.reviews
ADD VECTOR INDEX reviews_index review_embeddings
TYPE MSTG
""")
到目前为止,我们已经完成了应用的后端部分。现在,是时候专注于使用DronaHQ构建前端了。让我们看看如何做到这一点。
# 构建DronaHQ上的应用
DronaHQ是一个低代码应用开发平台,专为快速创建自定义Web和移动应用程序而设计。借助其强大的构建块,如预构建的UI组件、数据连接器和工作流自动化工具,DronaHQ大大减少了开发所需的时间和精力,使您能够快速构建应用程序,而无需处理复杂的前端框架。
无论您是全栈开发人员、专注于后端或前端工作,还是刚开始作为开发人员的旅程,DronaHQ都可以轻松拖放UI元素、连接各种数据源和构建令人印象深刻的应用程序。
让我们创建一个工作应用程序,该应用程序在MyScale数据库上执行向量搜索,并构建一个餐厅推荐界面。
# 将MyScale与DronaHQ集成
要将MyScale与DronaHQ集成,您可以利用ClickHouse连接器,因为MyScaleDB在内部使用ClickHouse。以下是如何设置它:
- 选择ClickHouse连接器:在DronaHQ中,导航到连接器部分,选择ClickHouse连接器。这将作为与MyScaleDB连接的接口。
输入MyScaleDB凭据:填写MyScaleDB实例的必要详细信息:
- 数据库URL:您的MyScaleDB实例托管的终端节点。
- 用户名和密码:您的身份验证凭据。
- 数据库名称:除非您的设置指定了不同的数据库,否则将其设置为
default
。
测试和保存:输入凭据后,点击“测试”以确保成功建立连接。如果测试通过,请保存配置。这将在DronaHQ中创建一个连接器,可以与您的MyScaleDB进行交互。
通过遵循这些步骤,您将在DronaHQ中拥有一个完全功能的连接器,可以与MyScaleDB进行通信,执行查询、获取数据,并为您的应用程序提供高级数据库功能。
# 为餐厅查找器编写查询
在DronaHQ中配置了MyScaleDB连接器后,我们现在可以编写查询,根据用户输入获取餐厅推荐。查询将根据用户的菜系偏好和价格范围动态调整。
# 查询1:获取初始餐厅推荐
首先,我们需要检索与用户偏好的菜系类型匹配且在其指定的价格范围内的餐厅列表。以下查询可以实现这一目标:
查询:
SELECT * FROM default.restaurants
WHERE cuisine LIKE '%{{cuisine_pref}}%'
AND price_range < {{price}}
LIMIT 10;
解释:
default.restaurants
:指的是MyScaleDB中存储餐厅数据的表。cuisine LIKE '%{ { cuisine_pref } }%'
:此条件根据用户的菜系偏好筛选结果。是DronaHQ动态替换为实际用户输入的占位符。
price_range < { { price } }
:将餐厅筛选为价格低于用户指定预算的餐厅,{ { price} }
是表示用户指定预算的占位符。LIMIT 10
:限制结果为前10个匹配的餐厅,以确保查询返回可管理的推荐数量。
# 查询2:执行向量搜索以获取增强推荐
在呈现初始餐厅列表后,我们希望使用向量搜索根据初始选择的特征提供额外的推荐。这使得应用程序可以建议在概念或体验上相似的餐厅,即使它们在关键字上不完全匹配。
查询:
SELECT *, distance(cuisine_embeddings, {{embedding}}) AS dist
FROM default.restaurants
ORDER BY dist
LIMIT 5;
解释:
distance(cuisine_embeddings, { { embedding } }) AS dist
:此表达式计算每个餐厅菜系的向量嵌入与用户偏好菜系嵌入之间的距离。{ { embedding } }
占位符表示用户的菜系偏好转换为向量,然后与存储在数据库中的cuisine_embeddings
进行比较。ORDER BY dist
:结果按计算的距离排序,距离最近的匹配(即距离最小的匹配)出现在前面。LIMIT 5
:限制结果为前5个最接近的匹配,确保推荐是高度相关的。
标准SQL过滤和向量搜索的组合使应用程序能够提供精确和上下文相关的餐厅推荐,提升了整体用户体验。
# 设计界面
在设计餐厅查找器时,我们的主要重点是创建一个高度功能性的界面。DronaHQ广泛的组件库使得以最少的编码工作实现这一目标成为可能。
应用程序首先允许用户从下拉菜单中选择他们喜欢的菜系,并通过价格范围滑块调整预算,立即反馈以细化搜索。推荐结果以响应式卡片的形式显示,卡片上显示餐厅的名称、评分和每餐价格,使用DronaHQ的网格布局排列。为了提高用户体验,推荐结果分为“餐厅推荐”和“我们认为您可能会喜欢”的部分,提供有针对性和探索性的选择。
# 构建动作流以显示结果
在您的数据库查询和UI准备就绪后,最后一步是建立一个动作流 (opens new window),触发这些查询并实时向用户显示结果。
首先,导航到应用程序中按钮组件的动作流配置。这是您将添加必要的连接器操作以与查询进行交互的地方。
- 将查询与用户输入关联
选择用于根据用户输入获取餐厅详细信息的查询。在变量部分,将输入字段(例如菜系类型和价格范围)与UI中的适当组件相关联。这样可以确保查询使用用户提供的数据。在链接这些字段后,测试动作流以确保其正常工作,然后保存配置。
- 使用嵌入查找相似选项 一旦第一个查询成功检索到数据,设置另一个连接器操作,触发基于嵌入的搜索。此搜索使用先前查询结果的嵌入数据(特别是嵌入数组的第0个索引)来查找相似选项。此步骤增强了向用户显示的结果的相关性。
- 在UI中显示结果 最后一步是设置控件值。通过正确设置控件值,您可以实现根据用户输入动态更新的动态显示,确保从查询检索到的数据在用户交互的UI组件中正确显示。
通过这些步骤,您将建立一个动作流,它会根据用户输入触发查询并将结果实时显示给用户。
# 结论
通过将MyScaleDB的向量搜索功能与DronaHQ的低代码环境相结合,我们创建了一个复杂的餐厅查找器,提供高度个性化的推荐。这种集成不仅可以根据用户偏好进行精确过滤,还通过先进的嵌入技术通过建议类似的餐厅来提升体验。
除了餐厅查找器,MyScaleDB和DronaHQ的组合还可以应用于各种其他场景,如构建智能聊天机器人,甚至是大型语言模型(LLMs)的观察系统。向量数据库的灵活性与低代码平台相结合,加速了开发,同时又不牺牲现代AI应用所需的复杂性。这样可以实现更快的原型开发、可扩展性,并能够无缝集成高级功能到日常应用程序中,同时节省开发时间。
本文最初发表在DronaHQ (opens new window)上。