dot Redis 8 来了——而且它是开源的

了解更多

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

本教程将帮助您使用基于内容的过滤和向量相似性搜索,为电子商务系统构建实时产品推荐系统。请跟随学习基本步骤和其工作原理。

推荐系统对于大多数在线业务,特别是对于 电子商务网站 来说,是一项重要的技术。它们是产生良好转化和维护客户忠诚度的关键要素。

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

diagram of a phone app

构建一个现代电子商务网站的推荐系统涉及诸多挑战。这仅是需要考虑的一部分问题

  • 个性化定制: 客户希望根据价格范围、品牌和尺寸等条件过滤结果。我们的系统应仅推荐符合这些参数范围内的产品。
  • 多模态: 产品列表不仅仅是文本描述。它还可以包含图像、视频、音频和 3D 模型等。在提供推荐时,应充分利用所有可用数据模态。
  • 延迟: 客户期望推荐结果能够快速出现。如果系统推荐的结果没有立即返回,它们就变得无关紧要了。
  • 数据量: 网站的产品和客户越多,高效推荐产品的难度就越大。即使面对大数据集,计算推荐结果也应保持快速。

随着这些需求的演变,构建推荐系统的方法也需要随之发展。在这篇博客文章中,我们将向您展示如何利用最新的 向量搜索技术 ,根据用户定义的过滤器构建实时产品推荐系统。该工具集包括 Redis 和 DocArray,但无论您使用何种工具,这种方法都适用。

推荐系统基础知识

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

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

本篇博客文章重点介绍如何改进基于内容的过滤方法。如果您是该领域的新手,建议您先阅读 Google 的概述,了解基于内容的过滤。

在实现基于内容的过滤时,有两个重要考虑因素

首先,当您将用户和商品建模为特征向量时,利用数据的各种模态非常重要。简单依赖关键词或一组人工设计的特征可能无法有效表示复杂数据。

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

用于表示文本和图像数据的知名模型之一是 CLIP。因此,在本教程中,我们使用 CLIP-as-service 作为驱动我们推荐系统的推理引擎。

此外,如果计算不高效,计算向量相似度可能会很慢且成本高昂。我们的应用要求(尊重用户过滤器并提供低延迟推荐)使得在批处理作业中预先计算商品和用户资料之间的相似度变得不切实际。这就是为什么实时计算向量相似度至关重要,可以利用诸如 Hierarchical Navigable Small World (HNSW) 等高效技术。

这些技术在向量数据库中实现。Redis 在 RediSearch 2.4 中提供了向量搜索能力。由于 Redis 是一个内存数据库,推荐商品既快速又是在实时环境中完成的。

特征表示和向量相似性计算已经讨论过,我们仍然需要一个数据结构来弥合多模态数据与向量数据库之间的差距。为此,我们使用 DocArray。可以将 DocArray 视为一个通用的 向量数据库 客户端,支持多模态数据。它提供了 Python 式的接口,只需几行代码即可轻松构建推荐系统。

docarray ingestion

解决方案设计

我们为本应用准备了工具:用于向量相似性搜索的 Redis,用于编码视觉数据的 CLIP-as-service,以及用于表示多模态文档和连接 Redis 的 DocArray。在本教程中,我们将应用这些技术来构建一个基于内容的过滤推荐系统。 

步骤如下

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

在接下来的说明中,我们用于产品推荐的数据来自 Amazon Berkeley Objects 数据集,这是一个包含 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 数据集包含产品项目以及图片和元数据(如品牌、国家和颜色)。它代表了一个电子商务网站的库存。

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 数据集的样本。我们可以使用 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 推理的 token

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

然后我们可以开始编码数据。务必将创建的 token 传递给 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 免费套餐