推荐系统已经成为我们生活中不可或缺的一部分。这些智能算法对于塑造我们的在线体验、影响我们消费的内容、我们购买的产品和我们探索的服务至关重要。无论我们是在Netflix等平台上播放内容,在Spotify上发现新音乐,还是在线购物,推荐系统都在幕后默默地工作,以个性化和增强我们的互动。
这些推荐系统的独特之处在于它们能够根据历史行为和用户模式理解和预测我们的偏好。通过分析我们过去的选择,这些系统会提出量身定制的建议,节省我们的时间和精力,同时向我们介绍符合我们兴趣的内容/产品。这提高了用户满意度并促进发现,向我们介绍我们可能不会遇到的新的相关产品。
在较高层面上,开发人员了解这些算法是由机器学习和深度学习系统(可互换地称为神经网络)提供支持的,但是如果我告诉您有一种方法可以构建推荐引擎,而无需经历部署神经网络的痛苦网络或机器学习模型?
这个问题在早期和中期初创公司的背景下特别相关,因为他们没有大量的结构化数据来训练他们的模型。正如我们所知,如果没有适当的训练数据,大多数机器学习模型将无法给出准确的预测。
我最近为一个项目构建并部署了一个基本的推荐引擎
我有一个广泛的
从较高的层面来看,从工程角度来看,我们有以下要求 -
系统应该能够以关键字的形式捕获用户的兴趣。系统还应该能够对用户对特定关键字的兴趣程度进行分类。
系统应该能够捕获用户对其他用户的兴趣。它应该能够对用户对另一个用户创建的内容的兴趣程度进行分类。
系统应该能够根据用户的兴趣生成高质量的推荐。
系统应该能够确保用户已经查看/拒绝的推荐在 X 天之内不会再次出现。
系统应该具有逻辑来确保来自同一创建者的帖子不会分组在同一页面上。系统应该尽力确保如果用户消费十个帖子(我们的页面大小),所有这些都应该来自不同的创建者。
系统应该很快。 P99 延迟小于 150 毫秒。
所有其他非功能性需求,例如高可用性、可扩展性、安全性、可靠性、可维护性等,都应该得到满足。
同样,这是一个高度过于简单化的问题陈述列表。事实上,这些文档有 3000 多个字长,因为它们还涵盖了将此推荐引擎集成到我们现有系统时可能出现的许多边缘情况和极端情况。让我们继续讨论解决方案。
我将一一讨论问题的解决方案,然后描述整个系统的整体工作原理。
为此,我们创建了一个名为
从上图中可以看出,我们存储了大量信息,例如交互次数(点赞、评论、分享)和这些交互的新近度(最后一次发生的时间)作为两个用户之间以及两个用户之间的关系数据用户和兴趣。我们甚至存储两个不同兴趣关键字之间的关系。我用了
这些兴趣关键词主要是名词。有一个系统可以将帖子的内容分解为这些关键字(名词)。它由AWS comprehend 提供支持;自然语言处理 (NLP) 服务,使用机器学习将文本分解为实体、关键短语等。同样,您可以使用任何托管 NLP 服务(有多个可用)来完成相同的任务。您不需要学习或部署机器学习模型!如果你已经了解机器学习,那么你可以去查看
下图是系统工作原理的简化高级表示。
虽然上面的内容看起来很简单,但每一步都有很多事情要做,必须仔细考虑这些事情,然后进行编程,以确保系统以最佳状态运行。
让我一步步解释:
要生成这些推荐,首先,我们必须将帖子的内容转换为名为 -
为了生成矢量嵌入,您可以使用任何著名的嵌入模型,例如OpenAI 嵌入模型、 Amazon titan或任何开源文本嵌入模型,具体取决于您的用例。我们选择了Amazon Titan ,因为它的价格实惠、性能好且操作简便。
现在,事情变得有趣了。您可能希望根据您的特定业务需求来设计查询。例如,在查询兴趣时,我们对参与度的新近度给予比特定关键字或用户的参与度更多的权重。我们还运行多个并行查询来查找用户的不同兴趣类型 - 关键字或其他用户。由于我们为单个用户生成多个提要,因此我们还会根据趋势运行一些宣传特定主题的查询(例如,在圣诞节附近您会看到许多与圣诞节相关的帖子,或者如果发生了地震,您会看到许多与地震相关的帖子)。不用说,只有当用户在旅程中表达了对这些主题的兴趣时,该主题才会出现在查询结果中。
因此,选择适合您的业务用例的逻辑以及您想要驱动和运行多个查询的行为,以获得所有用户兴趣的足够大的列表。
矢量数据库主要用于执行特定类型的搜索,称为
缓存数据库,因为我们需要解决的问题之一就是速度。我们使用Redis排序集来存储特定用户的帖子的唯一 ID。我们使用 Redis 排序集,因为用户提要中的帖子顺序至关重要。另外,您必须解决的另一个问题是“系统应该具有逻辑来确保来自同一创建者的帖子不会分组在同一页面上”。为了避免来自同一创建者的内容重复,我们编写了一个简单的算法,确保如果将特定创建者的帖子插入到特定用户的提要(排序集)中的任何位置,我们不会插入来自同一创建者的其他帖子连续十个位置(在向最终用户提供提要时,我们的页面大小为 10,因此我们保持静态以避免复杂性)。
为了决定用户特定推荐的顺序,我们考虑了以下因素 -
该用户与特定兴趣(或其他用户)的关系强度:它由从社交图中获取各种数据点的算术公式确定。所有这些都是参与度数据,例如最后创建的点赞的时间戳、创建的点赞数量、最后的评论等。用户参与行为是他们对某事物感兴趣的指标。
帖子在平台上的受欢迎程度:为了确定这一点,我们创建了一种算法,该算法考虑了各种因素,例如参与度、参与度与印象数比率、参与的唯一用户数量等,以生成该帖子的参与度分数在平台级别发布。
在某些提要中,我们优先考虑受欢迎程度;在其他情况下,我们会优先考虑社交图谱。但大多数情况下,它们都是两者的健康组合。
从上图中可以看出,系统有意保持非常简单。以下是系统的工作原理 -
当用户 A 创建帖子时,帖子服务在保存该帖子后会向队列触发发布/订阅事件,该事件由用于候选生成的后台服务接收。我们用
该后台服务异步接收此信息并执行前面讨论的功能 - 隐私检查、审核检查和关键字生成,然后生成向量嵌入并将其存储在向量数据库中。我们正在使用
每当用户在更新我们的主 NoSQL 数据库后参与(点赞/评论/分享等)时,后期服务就会触发推荐引擎服务的发布/订阅事件。
该推荐引擎服务更新图形数据库,然后通过执行 ANN 搜索和更新 Redis 数据库来近乎实时地更新用户的推荐源。因此,用户互动越多,提要就越好。有一些检查可以确保建议不会偏向于特定的关键字列表。这些检查是在我们查询图形数据库时执行的。该服务还异步更新参与度分数。参与度分数也会根据查看帖子的用户重新计算。
由于上述所有步骤都是在后台异步执行的,因此这些计算不会影响最终用户体验。
feed最终通过feed服务提供给最终用户。由于该服务仅在 Redis 和我们的主 NoSQL 数据库上执行查找(
一些服务已经写在
我们正在使用
我们用
正如您可以想象的那样,可以调整相同的设置来为任何用例构建基本的推荐引擎。但是,由于我们的网络是一个社交网络,因此我们需要进行一些调整以使该系统更加高效。
社交图层面需要机器学习/深度学习算法来预测与用户最相关的关键词和用户。目前,数据集太小,无法准确预测任何内容,因为它是一个非常新的产品。然而,随着数据的增长,我们将需要用机器学习算法的输出来替换当前的简单查询和公式。
各种关键词和用户之间的关系必须进行微调,变得更细化。他们现在处于非常高的水平。但他们需要更深入。我们需要探索图中的二度和三度关系,以首先完善建议。
我们目前没有对嵌入模型进行任何微调。我们需要在不久的将来这样做。
我希望您觉得这个博客有帮助。如果您有任何问题、疑问或建议,请随时通过以下方式与我联系
也发布在这里。