跳转至

05 策略建模:为什么AI系统能够猜你所想?

你好,我是Tyler。

今天我们要进入一个全新的章节——架构基础篇。上节课我们提到了,AIGC系统是从AIRC系统演化而来的

这节课开始,我们一起来探索目前AIRC系统中已经成熟的一些范式。它不仅是AI大模型记忆增强和可信人工智能的重要组成部分,也是许多大模型系统设计范式的来源,相信学完这一讲,你对AIGC系统的核心工作会更加熟悉,后续的学习也会有的放矢。

AIRC系统

AIRC 系统你应该已经很熟悉了,谷歌的搜索引擎、抖音的推荐系统,还有阿里妈妈的计算广告系统,这类系统的统称是“内容推荐系统(AIRC)”,它们已经渗透到了我们生活的方方面面。

但是,说起这类系统的架构,我们充其量只是借助Netflix的架构图,看到过它的一些外貌特征。而这个外形只是 AIRC 系统的冰山一角,并没有交代它的主要挑战和问题是什么。

所以跟着这样的架构图去建立系统,相当于跟着简笔画去学习如何素描,这是不太现实的。你看一下后面的图片就会明白了。

只有亲身经历过的人才知道,AI系统的背后隐藏着无数的技术细节。从业务指标的建模到系统架构的设计,从数据的收集和处理,到算法的选型和实验,这里的每一个环节,都要精心地设计、不断地优化。

那为了帮助你看见AIRC系统的原貌,掌握核心原理和设计原则,为学习AI大模型系统,打下一个良好的基础,我将带你学习AIRC系统架构的建模方法。

那根据我的实践经验啊,AIRC系统可以分成三大部分的工作,分别是策略建模、数据工程和模型工程,这三部分的工作,在后面的AI大模型系统当中也随处可见。

这节课我们就来聚焦策略建模这个部分。策略建模起到了提纲挈领的作用,对业务目标进行数学建模,后面讲到的内容也几乎都是为它而服务的。

从业务目标到最终的AIRC系统,要经过两次转化:首先是产品经理和算法专家将业务目标形式化,这一步会将业务上的玄学问题转变为明确的数学问题。在下一步,算法专家和架构师会把数学问题解构成工程问题,工程转化过程中,最主要的工作是召回、排序、控制博弈和风控几个部分。

我们先从策略建模开始说起。

指标建模

首先是指标建模,我们先要确定“北极星指标”,它是业务追求的终极目标,虽然它可能根据实际情况的变化而变化。但相对而言,在一段时间内,它是最稳定、明确的指标,是我们后续行动的基础。这里我以电商系统为例带你学习。

你可能听说过,电商系统通常把 GMV 指标作为北极星指标。为了提升这个指标,算法工程师们会想尽办法,在用户进入产品时把他最可能购买的商品放在最显眼的位置。

思考一下,如果让你来负责这个目标,你会怎样实现它呢?

如果我换一种方式表达,你就会豁然开朗了。我把前面这句话做个“中译中”,那问题就变成了“从海量商品中选出此人最可能成交的商品”。这是你再熟悉不过的排序算法了,排序的实体是商品,排序的值是商品被此人购买的概率。

在想清楚之后,你会发现,电商系统的本质是对商品进行排序,优先展示排序靠前的内容。

是不是逐渐的明朗了?接下来,你只要关注两个问题,一个是如何得到排序的概率值。第二是,如何对海量商品进行在线“实时”的排序。

我们先来解决第一个问题。先回想下你购物时的场景是怎样的:首先你会打开应用,搜索商品,然后点击加购按钮,或者是直接下单,最后填写地址,进行付款。

刚刚的一系列动作就叫“转化漏斗”,因为用户在任何步骤停止动作,都会打断成交的过程。你可以看一下文稿,我画了一张图来帮助你理解。那如果系统,能够预判你每一步发生的概率,就能计算出最终的成交概率了。

因此,某个商品对你展示过后的预期收益,可以用点击率,加购率,付款率和客单价的乘积来表示。当然,这里的公式是一个简化版,实际系统更加的复杂。

期望收益=点击率*加购率*付款率*客单价

这样你已经找到了第一个问题的答案,那就是将用户对每个商品的期望收益进行排序,将排名靠前的商品,展示给用户,早期的AIRC系统采用的就是这种方式。

那接下来,我们再来探讨第二个问题,如何对海量的商品做在线实时的排序。

现在的内容分发系统里面的物料总量往往非常庞大,比如谷歌现在的搜索文档规模已超过了62PB。同时,为了更精确地预测,这类系统往往会对高维大规模数据,做深度模型的建模。对于这么大的数据规模,在线实时打分排序是不现实的。

你可以对照文稿,来看看后面这张示意图。

所以,AIRC系统往往会拆分为召回和排序两个模块,这是在线系统中常用的效率权衡方法,接下来我们来学习这两个模块的原理,学完之后,你就会明白我为什么这么说了。

召回模块

召回模块的核心目的,就是用时间复杂度较低的算法排除大量的“错误答案”,减少排序算法的压力。

比如搜索引擎,常常会通过搜索词中的关键字,在倒排索引中拉取内容,大幅度地降低排序规模,让用户更快得到搜索结果。

这个方法叫做关键词召回,它只是众多召回策略里最简单的一种。常见的召回策略还包括年龄、性别这类用户画像召回方法,只要对内容对应的标签建立倒排索引就可以了。

选择一个好的召回策略,通常需要对业务有深入的洞察,针对业务平台的属性来设计特定的策略,比如基于性别的召回策略,就利用了类似“女性不太会买渔具,男性不太会买假睫毛”这类生活经验。

在召回阶段,我们需要放弃某些低潜力的商品,所以所有的召回策略,都可能导致最优结果的流失。还是沿用性别例子:如果夫妻共用一个账号,性别策略很可能会起到反作用。

所以后来发展出了向量召回技术,该技术基于对比学习和图神经网络,刻画用户和商品之间的空间距离,以此作为召回顺序的依据。

我为你准备了一张向量召回系统示意图,你可以理解一下它的大致思路。至于具体细节呢,我会在后面的课程详细讲解。

排序模块

排序模块负责对召回结果进行精确的打分排序。这里将会使用用户、场景和商品的全景特征进行模型建模,尽可能地去提高打分的准确度。

你可以看看后面这张图,画的是排序的全过程。

在排序过程中,要对漏斗里涉及到的各个行为概率进行预测。最经典的莫过于点击行为的预测。这类任务当中,常见的有Wide&Deep、DeepCross等模型,你可以暂且把它当成预测概率的黑盒。

另外,我们提到的召回和排序是性能上的一个取舍,这种取舍在排序的内部会再一次出现。为了满足发展需求,排序阶段也会进一步拆分为粗排、精排和重排。一般来说,较前阶段用到的排序算法要更快,相应的模型也更简单。

这里插一句题外话,根据以往的经验,排序模型会随着算力的提升,慢慢进入到较前的阶段使用,比如“淘汰”的精排模型,会逐渐成为粗排的主流模型。

到目前为止,你已经掌握AIRC系统的主要内容了。

控制&博弈

为了让系统变得更实用,我们进一步代入真实场景的需求。如果想让某个商品的曝光分布,跟后面的这张图一致,你能做到么?

广告系统当中为了让预算不在一早就全部花光,能在24小时中均匀的消耗,要求系统有能力,控制内容的曝光分布。面对快速、大量的流量请求,我们如何准确地控制分布呢?

这类问题是控制论算法的范畴,最好的方法就是用以PID和强化学习为代表的控制算法。控制类算法是AIRC系统当中的重要部分,它在AIGC系统当中也起到了重要作用,这里你先对它有一个印象即可。

下面我们再聊聊计算广告系统中,存在的典型博弈场景:广告业务上会分成,流量卖方 SSP 系统和流量买方系统 DSP 两大部分,卖方的目标是帮媒体最大化流量变现收益。而买方系统,则是要帮广告主低价买到适合自己的流量。

这时候呢,就会出现一个广告交易市场 Ad Exchange 来负责流量的拍卖,调和上下游的供需关系。在卖方给出流量特征信息后,买方们来实时报价进行竞拍。

这里就涉及到博弈论中的拍卖算法。

在这个场景下,卖方往往会制定拍卖策略,根据估价给出“拍卖底价”,不让买方“捡漏”。这样呢,买方才会给出较高的报价,后面课程中,还会对双方的博弈有更详细的讲解。

风控模块

现在一切都看上去那么美好,但可能你的系统上线不久后,就不得不停止服务。这是为什么呢?

图中是黑灰产常用的手机墙,手机墙中的每个设备,会模仿真实用户做出恶意刷单,虚假广告点击这类行为。这些行为会对你的客户造成巨大的伤害。

这里你会发现,工业级的系统最大的特点是要考虑线上风险。你需要和陌生对手,甚至自己的恶意用户,去进行竞争博弈。这也就催生出了风控模块。

风控模块一般包含内容安全系统和反作弊系统。

内容安全系统会对各种模态(视频,图像,语音,文字)物料做安全审核,确保平台投放的内容是符合你们平台形象和法律法规要求。该系统由机审和人审配合完成。

由于不合规内容占比相对较低,所以机审会采用高召回的策略,也就是“宁可错杀也不漏过”。在机筛之后,会把相对少量的内容交给运营人员做二次确认。

反作弊系统,在技术上可分成实时和离线反作弊这两个部分。实时反作弊一般会通过流量的行为模式还有动作频次来识别攻击者,这部分工作可以防御80%以上的攻击者。

但是根据二八定律,剩下的攻击会造成了客户更大的损失,通常这些攻击者的技术能力比较强,要靠离线反作弊来发现,因为离线系统能用到的数据和技术手段更多,可以发现长周期的异常流量、挖掘作案团伙。具体的算法会在后几节课展开学习。

小结

今天的内容告一段落,我带你做个回顾总结。

这一讲我们学习了AIRC系统如何对海量的内容进行在线实时的排序。

我们先要给系统设定北极星指标,并通过业务特点进行漏斗建模,之后将系统抽象成召回,排序两个模块,来提高排序效率,完成海量内容的在线实时排序。

除此之外,你还学习了如何使用控制、博弈和风控模块,让系统拥有控制能力,保证业务处于安全的状态。

现在对你来说,AIRC系统“冰山”下的轮廓已经逐渐清晰,后面大模型系统其实也大同小异。恭喜你学到这里,课中的细节会在接下来几讲中一一展开,敬请期待!

思考题

为了更好地理解这一讲的内容,你可以从后面这几道思考题中任选一道或者几道回答一下。

  1. 构建一个程序,支持根据文档中出现的内容,搜索本地所有文本文档,你觉得应该分为哪几个步骤?(提示:倒排索引)
  2. 如果需要根据你的使用习惯,让程序猜测你现在要使用哪个文件,把排名前十的文件推荐给你,要求将时延控制在100ms内,你会怎么做?(提示:多路召回)

恭喜你完成我们第 5 次打卡学习,期待你在留言区和我交流互动。也欢迎你把这节课分享给身边朋友,和 TA 一起学习进步。

精选留言(11)
  • 顾琪瑶 👍(11) 💬(1)

    1. 可以采用传统的搜索引擎的思路来做, 先将文档中的内容进行分词, 并为词项建立索引, 词项与文档号进行关联, 搜索时根据词项找到文档进行检索 2. 多路召回还是有不明白的地方, 是指使用多种不同的召回策略多对一批候选物料进行检索吗? 如果是的话, 那最后是否可以将候选的物料特征进行乘积, 最后做排序来选择? 延时控制的话可以考虑每个节点执行不动的召回策略再主节点进行合并排序

    2023-08-21

  • GAC·DU 👍(4) 💬(2)

    # 多角度捕捉,合并组合推荐结果,关于性能使用了简单的倒排索引,还可以用并行和加权等方式提升性能,定期对多路召回算法的性能进行测试和评估,以识别潜在的性能问题并及时进行优化。 import time class FileRecommendationSystem: def __init__(self, file_database): self.file_database = file_database self.inverted_index = self.build_inverted_index(file_database) def build_inverted_index(self, file_database): inverted_index = {} for file_id, content in file_database.items(): words = content.split() for word in words: if word not in inverted_index: inverted_index[word] = [] inverted_index[word].append(file_id) return inverted_index def recall_by_query(self, query): query_words = query.split() potential_files = set() for word in query_words: if word in self.inverted_index: potential_files.update(self.inverted_index[word]) return potential_files def recommend_files(self, query, num_recommendations=10): recall_1 = self.recall_by_query(query) recall_2 = self.another_recall_algorithm(query) recall_3 = self.yet_another_recall_algorithm(query) merged_recall = recall_1 | recall_2 | recall_3 recommended_files = [] for file_id in merged_recall: recommended_files.append((file_id, self.file_database[file_id])) recommended_files.sort(key=lambda x: x[0]) return recommended_files[:num_recommendations] def another_recall_algorithm(self, query): return set([file_id for file_id, content in self.file_database.items() if "orange" in content]) def yet_another_recall_algorithm(self, query): return set([file_id for file_id, content in self.file_database.items() if "apple" in content])

    2023-08-21

  • 极客雷 👍(1) 💬(1)

    你是谁?严重怀疑是AI回复评论,哈哈

    2023-12-11

  • Lucky+ 👍(1) 💬(1)

    1. 文档预处理:这是第一步,需要将所有的文档读入程序,进行必要的预处理。预处理可能包括去除标点符号、数字、特殊字符等,转换所有的大写字母为小写,进行词干提取等。 2. 分词:将预处理后的文档进行分词,将每个文档分解为独立的词项(token)。 3. 建立倒排索引:倒排索引是信息检索中常用的数据结构,它将每个词项映射到出现该词项的文档列表。这样,当我们搜索一个词项时,就可以快速找到所有包含该词项的文档。 4. 查询处理:当用户输入查询时,程序需要将查询分词,并在倒排索引中查找每个词项。然后,系统可以通过一些策略(如布尔查询、向量空间模型等)来确定最相关的文档。 5. 结果返回:将搜索到的相关文档返回给用户。 6. 优化和更新:根据用户的反馈和使用情况,不断优化搜索算法,并定期更新倒排索引,以保持与文档库的同步。

    2023-09-04

  • 小耿 👍(0) 💬(1)

    请问老师,期望收益计算公示中的点击率、加购率和付款率是如何得到的?

    2023-08-24

  • 张清荣 👍(1) 💬(0)

    AIGC 系统是从 AIRC 系统演化而来的? 上节课哪里提到了?

    2024-01-03

  • lw 👍(1) 💬(0)

    2、拿我自己举例,我要使用哪个文件大概率是最近一周点击最多的文件或者是此刻前打开的文件,二个影响因素做个加权,本质是个概率的问题

    2023-10-10

  • Seachal 👍(0) 💬(0)

    本课总结AIRC系统在AI与电商中的应用。首先,探讨AIRC架构,强调策略建模的重要性。电商中,指标建模提升GMV,排序算法作用显著。其次,召回与排序模块加速搜索展示,精确排序结果。同时,控制算法、博弈算法应用于广告系统,风控模块保障系统安全。总结而言,本课概述了AIRC系统的关键部分及其在电商的应用,深入解析了策略建模在AI系统中的作用。

    2024-11-23

  • 方梁 👍(0) 💬(0)

    很好

    2024-06-12

  • 周晓英 👍(0) 💬(0)

    第二个问题的思路: 理解需求: 首先,我们需要理解用户的使用习惯和倾向,这可能包括分析用户的历史行为数据,例如他们以前打开过哪些文件,花费的时间等。 我们也需要了解文件的内容和结构,以及可能影响用户需求的其他因素(例如,时间、任务类型等)。 数据准备: 收集并准备必要的数据,包括用户行为历史数据和文件元数据。 可能还需要构建用户和文件的特征,以便机器学习模型能够理解。 多路召回策略: 基于内容的召回:分析文件的内容,找到与用户过去交互过的文件内容相似的文件。 基于协同过滤的召回:利用其他相似用户的行为来推荐可能的文件。 基于时间的召回:考虑文件的时间相关性,例如最近修改过或最近访问过的文件。 基于热门度的召回:根据文件的流行程度或访问频率进行推荐。 基于序列的召回:考虑用户的行为序列,例如他们通常会在打开一个文件后打开哪些文件。 合并与排名: 将从不同策略中获得的候选文件合并成一个候选集合。 使用一个排名模型(例如,学习排序模型)对候选文件进行排名,以确定最相关的文件。 优化性能: 为了确保在100ms内返回结果,可能需要优化召回和排名算法的性能,包括使用索引、减少模型复杂度和/或采用分布式计算等。

    2023-10-02

  • GAC·DU 👍(0) 💬(0)

    # coding:utf-8 # 数据准备 -> 分词处理 -> 建立倒排索引 -> 搜索处理 -> 排序 -> 返回结果 class InvertedIndex: def __init__(self): self.index = {} # 追加数据,做简单的分词处理 def add_document(self, doc_id, content): words = content.split(" ") for word in words: if word not in self.index: self.index[word] = [] if doc_id not in self.index[word]: self.index[word].append(doc_id) # 搜索处理,返回包含该单词的文档列表 def search(self, query): if query in self.index: return self.index[query] else: return [] index = InvertedIndex() # 准备追加数据 index.add_document(1, "apple banana") index.add_document(2, "banana orange") index.add_document(3, "apple apple apple") index.add_document(4, "苹果 香蕉 葡萄") index.add_document(5, "苹果 葡萄 葡萄 葡萄") # 搜索单词并返回包含该单词的文档列表 result = index.search("apple") print("Documents containing 'apple':", result) result = index.search("banana") print("Documents containing 'banana':", result) result = index.search("orange") print("Documents containing 'orange':", result) result = index.search("grape") print("Documents containing 'grape':", result) result = index.search("葡萄") print("Documents containing '葡萄':", result)

    2023-08-21