dot 快速的未来正在您所在的城市举办的活动中。

加入我们参加 Redis 发布会

如何使用 Redis 和 DocArray 构建实时产品推荐系统

本教程帮助您使用基于内容的过滤和向量相似性搜索,为电子商务系统构建实时产品推荐系统。请继续阅读以了解基本步骤及其工作原理。

推荐系统是大多数在线业务,尤其是电子商务网站的重要技术。它们是产生良好转化率和保持客户忠诚度的重要因素。

推荐系统通常会根据用户的个人资料和偏好,以及通过观察他们的行为(例如购买、点赞或查看商品)向用户展示商品。

diagram of a phone app

考虑为现代电子商务网站构建推荐系统所面临的挑战。这只是需要考虑的问题的一个子集

  • 自定义:客户希望过滤结果,例如按价格范围、品牌和尺码过滤。我们的系统应该只推荐符合这些参数的产品。
  • 多种模式:产品列表不仅仅是文本描述。例如,它还可以包含图像、视频、音频和 3D 网格。在进行推荐时,应利用所有可用数据模式。
  • 延迟:客户希望推荐能够快速显示。如果系统推荐不能立即返回,那么它们就无关紧要了。
  • 数据量:网站拥有的产品和客户越多,高效推荐产品就越难。即使数据量很大,计算推荐也应该保持快速。

随着这些需求的不断发展,构建推荐系统的途径也需要不断发展。在这篇博文中,我们向您展示了如何使用最新的向量搜索技术构建实时产品推荐系统,以尊重用户定义的过滤器。工具套件包括 Redis 和 DocArray,但无论您使用哪些工具,该方法都是相关的。

推荐系统基础知识

与任何其他计算问题一样,构建推荐系统有多种方法和工具来支持每项工作。它们包括

  • 协同过滤:系统根据类似用户的偏好预测与用户相关的商品。
  • 基于内容的过滤:系统将用户的兴趣建模为特征向量,并根据向量之间的相似性预测相关商品。
  • 混合方法:系统将协同过滤、基于内容的过滤和其他方法结合起来。

这篇博文重点介绍如何改进基于内容的过滤方法。如果您是此主题的新手,建议您先阅读 Google 对基于内容的过滤的概述

在实现基于内容的过滤时,有两个重要的注意事项

首先,当您将用户和商品建模为特征向量时,重要的是要利用数据的全部模式。仅仅依靠关键字或一组工程特征可能无法有效地表示复杂数据。

这就是为什么最先进的AI 模型很重要,因为它们将复杂的多模态数据表示为向量嵌入。

最著名的表示文本和图像数据的模型之一是 CLIP。因此,在本教程中,我们使用 CLIP-as-service 作为支持我们推荐的推理引擎。

此外,如果计算向量相似性效率不高,则可能很慢且成本很高。我们的应用程序要求(尊重用户过滤器并提供低延迟推荐)使得在批处理作业中预先计算商品和用户个人资料之间的相似性变得不切实际。这就是为什么在实时环境中使用高效技术(例如分层可导航小世界 (HNSW))来计算向量相似性至关重要的原因。

这些技术是在向量数据库中实现的。Redis 在 RediSearch 2.4 中提供向量搜索功能。由于 Redis 是一个内存数据库,因此推荐商品既快又可以在实时环境中执行。

在涵盖了特征表示和计算向量相似性之后,我们仍然需要一种数据结构来弥合多模态数据和向量数据库之间的差距。为此,我们使用 DocArray。您可以将 DocArray 视为通用的向量数据库 客户端,它支持多模态数据。它具有 Pythonic 接口,只需几行代码即可轻松构建推荐系统。

docarray ingestion

设计解决方案

我们已经为该应用程序组装了工具:用于向量相似性搜索的 Redis、用于对视觉数据进行编码的 CLIP-as-service 以及用于表示多模态文档并连接到 Redis 的 DocArray。在本教程中,我们应用这些技术来构建基于内容的过滤推荐系统。 

步骤如下

  • 将数据集加载到 DocArray 格式。
  • 使用 CLIP-as-service 对产品图像进行编码来对产品进行建模。
  • 通过计算最近查看的 k 个产品的嵌入的加权平均值来对用户个人资料进行建模。
  • 使用 DocArray 加载产品数据。
  • 在 Redis 中索引产品数据。
  • 使用Redis 向量相似性搜索向用户推荐最类似于用户浏览历史记录的商品,同时过滤这些结果以尊重用户偏好。

在以下说明中,我们用于产品推荐的数据来自 Amazon Berkeley Objects Dataset,该数据集包含 Amazon 产品及其元数据、目录图像和 3D 模型。

设置

第一步是配置 Redis 实例。您可以使用 Docker 创建本地 Redis 实例

docker run -d -p 6379:6379 redis/redis-stack:latest

接下来,我们需要安装 DocArray、Jina 和 clip-client

pip install docarray[redis] jina clip-client

这些是我们要进行的全部设置。现在我们已准备好开始探索数据。

数据集探索

Amazon Berkeley Objects Dataset 包含产品项目及其图像和元数据,例如品牌、国家/地区和颜色。它代表了电子商务网站的库存。

nia and nicole womens wallet

出于本教程的目的,我们可以从 Jina Cloud 下载此数据集的子集,该子集已预先处理为 DocArray 格式。

首先,使用终端对 Jina Cloud 进行身份验证

jina auth login

接下来, 下载数据集

from docarray import DocumentArray, Document
da = DocumentArray.pull('amazon-berkeley-objects-dataset', show_progress=True)

这将返回一个 DocumentArray 对象,其中包含来自 Amazon Berkeley Objects Dataset 的样本。我们可以使用 summary() 方法获得概述

da.summary()
╭────────────────────── Documents Summary ──────────────────────╮
│                                                               │
│   Type                   DocumentArrayInMemory                │
│   Length                 **5809**                                 │
│   Homogenous Documents   *True*                                 │
│   Common Attributes      **(**'id', 'mime_type', 'uri', 'tags'**)**   │
│   Multimodal dataclass   *False*                                │
│                                                               │
╰───────────────────────────────────────────────────────────────╯
╭───────────────────── Attributes Summary ─────────────────────╮
│                                                              │
│   **Attribute**   **Data type**   **#Unique values**   **Has empty value**   │
│  ──────────────────────────────────────────────────────────  │
│   id          **(**'str',**)**    **5809**             *False*             │
│   mime_type   **(**'str',**)**    **1**                *False*             │
│   tags        **(**'dict',**)**   **5809**             *False*             │
│   uri         **(**'str',**)**    **4848**             *False*             │
│                                                              │
╰──────────────────────────────────────────────────────────────╯

或者,我们可以使用 [plot_image_sprites()](<https://docarray.jina.ai/api/docarray.array.document/#docarray.array.document.DocumentArray.plot_image_sprites>) 方法显示第一个项目的图像。

da[:12].plot_image_sprites()
product catalog items

每个产品在 tags 字段中都包含元数据信息。 

让我们看看 tags 的内容

da[0].tags
{'height': '1926',
 'country': 'CA',
 'width': '1650',
 'product_type': 'ACCESSORY',
 'color': 'Blue',
 'brand': 'Thirty Five Kent',
 'item_name': "Thirty Five Kent Men's Cashmere Zig Zag Scarf, Blue"}

稍后,我们将使用这些元数据根据用户的偏好过滤推荐。

添加嵌入

要为我们的数据集创建向量嵌入,我们首先需要一个用于 CLIP-as-service 推理的令牌

# Create a Jina token to be used for CLIP-as-service inference
jina auth token create fashion -e 30

然后我们可以开始对数据进行编码。请确保将创建的令牌传递给 Client 对象

from clip_client import Client

c = Client(
    'grpcs://api.clip.jina.ai:2096', credential={'Authorization': 'your-auth-token'}
)

encoded_da = c.encode(da, show_progress=True)

对数据集进行编码需要几分钟。完成编码后,我们继续执行后续步骤。

连接到 Redis

此时,我们的数据已编码并准备好索引。 

为此,我们创建一个与 Redis 服务器连接的 DocumentArray 实例。重要的是要指定正确的嵌入维度和过滤列

# Configure a new DocumentArray with a Redis document store
redis_da = DocumentArray(storage='redis', config={
    'n_dim': 768,
    'columns': {
        'color': 'str',
        'country': 'str',
        'product_type': 'str',
        'width': 'int',
        'height': 'int',
        'brand': 'str',
    }
})

# Index data
redis_da.extend(encoded_da

有关详细信息,请参阅 DocArray 中的 Redis 文档存储

生成推荐

为了了解推荐逻辑,请考虑以下示例:Eleanor 决定给自己的衣橱添加一条围巾,并在我们的商店里查看了几条围巾。她最喜欢的颜色是海军蓝,而且预算必须在 25 美元以下。

我们的推荐功能应该允许指定这些要求,并根据浏览历史记录推荐商品,重点关注最近查看的商品。

因此,我们通过对最近查看的商品的嵌入进行加权平均来组合这些嵌入,从而对最近的商品给予更多权重

让我们实现一个函数,该函数根据最近查看商品的嵌入的加权平均值推荐商品,同时考虑用户过滤器。也就是说,在推荐的商品中,我们希望重点关注购物者最近查看的商品。 

因此,我们通过对最近查看的商品的嵌入进行加权平均来组合这些嵌入,从而对最近的商品给予更多权重

import numpy as np

def recommend(view_history, color=None, country=None):
    embedding = np.average(
        [doc.embedding for doc in view_history],
        weights=range(len(view_history), 0, -1),
        axis=0
    )

    user_filter = ''
    
    if color:
        user_filter += f'@color:{color} '
    
    if country:
        user_filter += f'@country:{country} '
    
    return redis_da.find(embedding, filter=user_filter)

向产品浏览添加推荐

为了在客户查看产品时显示相关的推荐,我们需要执行以下三个步骤

  1. 显示产品的图像和描述。
  2. 将产品添加到最近查看的 k 个产品的列表中。
  3. 显示与最近查看的 k 个产品相关的推荐。

我们可以使用以下函数来实现这一点

k = 5
view_history = []

def view(item: Document, view_history, color=None, country=None):
    print(item.tags['item_name'], ':')
    item.display()
    view_history.insert(0, item)
    view_history = view_history[:k]
    recommendations = recommend(view_history, color=color, country=country)
    recommendations.plot_image_sprites()
    return recommendations

查看结果

让我们试用几次。首先,让我们查看商店中的第一件商品及其推荐

recommended = view(redis_da[0], view_history

这将显示一条吸引人的围巾,标注为“Thirty-Five Kent Men's Cashmere Zig Zag Scarf, Blue”

gray scarf

……以及相应的推荐

assortment of scarves

它们满足用户过滤器的程度如何?

让我们检查推荐列表中的第三项,并应用一个 color=’Navy‘ 的过滤器,以确保更好的匹配。

recommended = view(recommended[2], view_history, color='Navy')

…这将生成更好的商品展示和推荐。

Thirty-Five Kent 男士羊绒之字形围巾,蓝色

navy scarf
digital store clothing items

现在,推荐功能返回与满足 color='Navy' 过滤器的围巾在视觉上最相似的商品。

成功!并且,可能还会带来新的电子商务销售。

综合起来

以上说明是简要概述,旨在展示为在线商店推荐商品的流程构建块。

欢迎您更进一步。我们创建了一个 GitHub 仓库,其中包含具有相同数据集和技术的商品商店界面的源代码。

vector similarity search

此演示仅向您展示了向量相似性搜索如何提供尊重用户偏好和过滤器选择的低延迟实时推荐。

但它有多快?让我们看看推荐查询的延迟数据。您可以在命令行控制台中找到日志。

Retrieving products ... Retrieving products takes 0 seconds (0.01s)

这意味着计算推荐大约需要 10 毫秒!

当然,仍然有改进的空间,尤其是在质量方面。例如,我们可以提出更复杂的方法来模拟用户的资料和兴趣。我们还可以整合更多类型的数据,例如 3D 网格和视频。这留给读者作为练习。

寻找更好的答案

向量相似性搜索是在实时环境中实施推荐的基本技术。

您的下一步

  • 使用最先进的 AI 模型将多模态数据编码成向量表示。
  • 在实时环境中使用向量数据库计算向量相似性。对于低延迟,内存数据库(如 Redis)是理想的选择。
  • 请参阅 Redis 文档了解更多信息。

使用 DocArray 作为处理多模态数据的便捷数据结构,以及与向量数据库交互。请参阅 DocArray 文档以开始使用,并与Redis AI/ML 团队联系以了解更多关于 Redis 向量搜索的信息。

Redis Cloud 免费层开始。