超越多模态向量:使用 Superlinked 和 Qdrant 进行酒店搜索
Filip Makraduli, David Myriel
·2025 年 4 月 24 日

不仅仅是多模态搜索?
人工智能已经改变了我们查找产品、服务和内容的方式。现在,用户使用自然语言表达需求,并期望得到精确、量身定制的结果。
例如,您可能搜索巴黎符合特定条件的酒店:
“艾菲尔铁塔附近、评价多、免费停车的平价奢华酒店。” 这不仅仅是一个搜索查询,而是一组复杂的、相互关联的偏好,跨越多种数据类型。
在这篇博客中,我们将向您展示我们如何构建了酒店搜索演示。
图 1: Superlinked 生成不同模态的向量,这些向量由 Qdrant 进行索引和服务,以实现快速、准确的酒店搜索。
这个应用之所以如此强大,在于它能将您的自然语言查询分解为精确的参数。当您在顶部输入问题时,您可以观察到查询参数在左侧边栏中动态更新。
在这篇博客中,我们将向您展示 Qdrant 和 Superlinked 如何结合文本理解、数值推理和类别过滤,创造无缝的搜索体验,满足现代用户的期望。
核心组件
图 2: 在典型的搜索或 RAG 应用中,嵌入框架 (Superlinked) 将您的数据及其元数据组合成向量。这些向量被摄取到 Qdrant 集合中并进行索引。
Superlinked 通过将数据嵌入到为每种属性类型设计的专用“空间”中,而不是使用单一的嵌入方法处理所有数据,从而使搜索更加智能。
当用户查询“艾菲尔铁塔附近、评价多、免费停车的平价奢华酒店”时,Superlinked 使用 LLM 进行自然查询理解并设置权重。这些权重决定了:
- 偏好方向(负值表示较低的值,正值表示较高的值)。
- 偏好强度(数值越大,影响越强)。
- 不同属性之间的平衡(例如,price_weight: -1.0 和 rating_weight: 1.0 是平衡的)。
这种灵活运用权重的方式使用户能够快速迭代、实验并实现业务逻辑或上下文,比从头重建整个搜索系统快得多。然后,Superlinked 应用强制性硬过滤器来缩小结果范围,再使用加权最近邻搜索对其进行排名,从而提供针对用户偏好量身定制的细致、准确的结果。所有向量都存储在 Qdrant 中。
SuperLinked 框架设置: 一旦您设置好 Superlinked 服务器,大部分原型工作就可以直接从示例 notebook 中完成。准备就绪后,您可以从 GitHub 仓库托管并通过 Actions 进行部署。
Qdrant 向量数据库: 存储向量最简单的方法是创建一个免费的 Qdrant Cloud 集群。我们有简单的文档向您展示如何获取 API 密钥并导入新向量以及运行一些基本搜索。对于此演示,我们已部署了一个正在运行的 Qdrant Cloud 集群。
OpenAI API 密钥: 对于自然语言查询和生成权重,您将需要一个 OpenAI API 密钥。
1. 向量空间:智能搜索的构建块
Superlinked 创新的核心在于空间 (Spaces) - 专为不同数据类型设计的专业向量嵌入环境。与强制将所有数据放入单一嵌入格式的传统方法不同,这些空间尊重不同数据类型固有的特征。
在我们的演示中,四个不同的空间协同工作:描述 (Description)、评分 (Rating)、价格 (Price) 和评分数量 (Rating Count)。它们的定义如下:
# Text data is embedded using a specialized language model
description_space = sl.TextSimilaritySpace(
text=hotel_schema.description,
model=settings.text_embedder_name # all-mpnet-base-v2
)
# Numerical data uses dedicated numerical embeddings with appropriate scaling
rating_space = sl.NumberSpace(
hotel_schema.rating,
min_value=0,
max_value=10,
mode=sl.Mode.MAXIMUM # Linear scale for bounded ratings
)
price_space = sl.NumberSpace(
hotel_schema.price,
min_value=0,
max_value=1000,
mode=sl.Mode.MAXIMUM,
scale=sl.LogarithmicScale() # Log scale for prices that vary widely
)
rating_count_space = sl.NumberSpace(
hotel_schema.rating_count,
min_value=0,
max_value=22500,
mode=sl.Mode.MAXIMUM,
scale=sl.LogarithmicScale() # Log scale for wide-ranging review counts
)
这种方法的强大之处在于,每个空间都能恰当地保留其领域内的语义关系,同时允许这些不同的空间组合成一个连贯的搜索体验。
价格被嵌入以保持其比例关系,文本嵌入捕获语义意义,评分保留其相对质量指标,而评分数量则使用对数缩放来恰当地权衡评论数量的重要性。
2. 超越多模态向量搜索:全景图
Qdrant 和 Superlinked 都支持丰富的多模态搜索环境,其中不同的数据类型协同工作而非竞争。对于我们的酒店演示,这意味着:
- 文本描述使用最先进的、理解语义的语言模型进行嵌入。
- 价格使用对数缩放以恰当地处理广泛的数值范围。
- 评分线性嵌入以保留其质量指标。
- 评论数量使用对数缩放以考虑额外评论带来的边际收益递减。
不同于在嵌入前将所有数据串联成文本(导致数字之间出现不可预测的非单调关系)的方法,或者维护不同属性单独索引的系统,Superlinked 创建了一个统一的搜索空间,其中可以同时考虑多个属性,并保留适当的语义关系。
声明这个统一的索引非常简单:
index = sl.Index(
spaces=[
description_space,
price_space,
rating_space,
rating_count_space,
],
# Additional fields for hard filtering
fields=[hotel_schema.city, hotel_schema.amenities, ...]
)
如果您想深入了解该算法以及多向量嵌入的工作原理,可以阅读我们的文章。
3. 智能查询处理:从自然语言到结果
Superlinked 中的查询处理系统简化了搜索查询的构建和执行方式。该系统允许用户使用自然语言进行交互,然后将其转换为多维向量操作,从而摆脱僵化的查询结构。
酒店演示中的查询构建展示了这种强大功能:
query = (
sl.Query(
index,
weights={
price_space: sl.Param("price_weight", description=price_description),
rating_space: sl.Param("rating_weight", description=rating_description),
# Additional space weights...
},
)
.find(hotel_schema)
.similar(description_space.text, sl.Param("description"))
.filter(hotel_schema.city.in_(sl.Param("city")))
# Additional filters...
.with_natural_query(natural_query=sl.Param("natural_query"))
)
分解查询
这种设置使得像“艾菲尔铁塔附近、评价多、免费停车的平价奢华酒店”这样的查询能够自动转换为:
- 对“奢华”和“艾菲尔铁塔”概念的文本相似性搜索
- 针对“平价”价格的适当加权(较低范围)
- 针对“免费停车”这一便利设施的硬过滤
- 搜索“大量”(评分数量)+ 良好评价(评分)
不同于依赖检索后重排(如果初始检索过于严格,可能遗漏相关结果)或元数据过滤器(将“平价”等模糊偏好转换为刚性边界)的系统,这种方法在整个过程中保持了搜索的细微差别。
4. 混合搜索的再想象:解决现代搜索问题
当今的搜索领域主要围绕混合搜索展开讨论——将关键词匹配用于精度,向量搜索用于语义理解。酒店搜索演示通过实现跨越文本检索方法和整个数据域的多模态混合搜索方法,进一步深化了这一概念。
在酒店搜索演示中,我们看到混合搜索在多个维度上的再想象:
- 文本混合搜索:结合精确匹配(用于城市名称、便利设施关键词)与语义相似性(用于“奢华”或“家庭友好”等概念)
- 数值混合搜索:融合精确范围过滤器(最低/最高价格)与基于偏好的向量相似性(用于“平价”或“高评分”等概念)
- 类别混合搜索:整合硬性类别约束(必须在巴黎)与软性偏好(偏好提供特定便利设施的酒店)
这种多维混合方法解决了传统搜索系统面临的挑战:
- 单模态向量搜索在查询跨越多种数据类型时会失效
- 传统的混合搜索仍然将关键词和向量组件分开处理,这意味着必须适当地权衡它们
- 每个属性单独存储会强制进行复杂的结果整合,从而丢失语义上的细微差别
- 纯粹的过滤方法将偏好转换为二元决策,忽略了偏好的“强度”
- 重排策略可能导致初始检索效果较弱,尤其对于宽泛的查询
这种统一的方法在多维搜索空间中维持了所有属性的语义关系,其中偏好成为权重而非过滤器,硬性约束和软性偏好在同一查询中无缝共存。
结果是搜索体验直观且“好用”——无论用户是在寻找“市中心附近评价良好的宠物友好型精品酒店”,还是“度假区内带泳池的平价家庭套房”——因为系统理解用户所询问内容的语义以及不同属性之间的关系。
酒店搜索演示展示了这一愿景的实际应用,预示着搜索的未来不仅理解我们使用的词语,还理解它们所代表的复杂、细微的偏好。
如何构建应用
更多详细信息,请查看仓库。
或者,您可以克隆此应用:
git clone https://github.com/superlinked/hotel-search-recipe-qdrant.git
后端位于 superlinked_app
下,而前端需要从 frontend_app
构建。
部署后端
使用 superlinked_app/.env-example
作为模板,创建 superlinked_app/.env
并设置 Natural Query Interface 所需的 OPENAI_API_KEY
,以及 Qdrant Vector Database 所需的 QDRANT_URL
和 QDRANT_API_KEY
。
python3.11 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
APP_MODULE_PATH=superlinked_app python -m superlinked.server
首次下载 sentence-transformers 模型需要一些时间(取决于网络)。
API 文档将可在 localhost:8080/docs 查看。
要摄取数据集,请在终端中运行此命令:
curl -X 'POST' \
'http://localhost:8080/data-loader/hotel/run' \
-H 'accept: application/json' \
-d ''
请等待摄取完成。您将看到消息提示。
在 Qdrant Cloud 控制面板中检查集合
摄取 Superlinked 向量后,登录 Qdrant Cloud 控制面板,导航至 Collections(集合),选择您的 default
酒店集合。
您可以在 Data(数据)选项卡下浏览各个点,查看载荷元数据(价格、评分、便利设施)及其原始向量嵌入。
在 Collection Information(集合信息)部分,您可以使用 Search(搜索)选项卡应用元数据过滤器或按向量搜索。在 Search Quality(搜索质量)部分,您还可以监控性能指标(吞吐量、延迟)。
扩展应用时,返回 Qdrant Cloud 控制面板 配置自动伸缩、备份和快照。这些选项将使您的服务保持可靠且经济高效。
构建前端
cd frontend_app
python3.11 -m venv .venv-frontend
. .venv-frontend/bin/activate
pip install -e .
python -m streamlit run app/frontend/main.py
前端 UI 将可在 localhost:8501 查看。
Superlinked CLI
注意: 如果您需要 Superlinked 用于大规模项目,可以使用 Superlinked Cloud。
通过“superlinked cli”,您将能够在大规模下运行 Superlinked 应用,包含批处理引擎、日志记录等组件。如需更多详细信息,请联系 Superlinked 团队:superlinked.com。