新闻详情

新闻详情

首页 / 资讯中心 / 详情

贝叶斯平滑在点击率预估与推荐系统冷启动中的应用

发布时间:2026/9/16 3:57:55来源:尧图网络
贝叶斯平滑在点击率预估与推荐系统冷启动中的应用
做点击率预测、广告排序或者推荐系统冷启动时贝叶斯平滑几乎是躲不开的一个坑。我刚接触这个场景时直接拿广告的展示数和点击数相除当作CTR结果前台上线的模型被业务方追着吐槽——展示次数只有几十次的物料点了一下CTR就报出几个百分点排序乱成一锅粥。后来把贝叶斯平滑引入到物料粒度的点击率预估流程里问题才算真正解决。这篇文章我会从最朴素的“为什么要平滑”讲起把贝叶斯平滑的数学原理掰开揉碎再给出一份可以直接落到代码里的实操步骤最后聊几个生产环境中容易踩的坑。如果你是刚接触广告算法、推荐系统召回排序或者正在处理任何“曝光少、点击更少”的稀疏计数数据这篇文章应该能让你少走不少弯路。即使你之前没怎么接触过贝叶斯统计按照文章里的推导和理解方式来走一遍也能明白贝叶斯平滑到底在做什么、每个参数是怎么来的。1. 为什么点击率预测离不开贝叶斯平滑1.1 直接算CTR的尴尬一个点击就能让0变成100%我们先把问题定义清楚。所谓点击率预测核心就是估算某个广告、商品或内容在给定场景下被点击的概率。在互联网广告和推荐系统里CTR不仅是衡量物料质量的核心指标还直接参与到广告计费、排序和流量分配的链条中。最朴素的想法是这样的一个物料曝光了N次被点击了C次那么这个物料的CTR就是C/N。听起来很简单对吧但真实数据几乎不会这么规整。一个刚上线的广告可能只展示了200次其中有1次点击那它的原始CTR就是0.5%另一个广告展示了100000次点击了500次原始CTR也是0.5%。按照这个逻辑两个广告的质量一样。但学过概率的人都知道基于大样本统计出来的0.5%和基于小样本偶然得出的0.5%置信度完全不是一个量级。更极端的情况是展示20次一个点击都没有CTR就是0但这能说明这个广告一点吸引力都没有吗显然不能。这就是计数数据稀疏性带来的核心问题。低频物料的点击率方差极大直接把经验CTR用于排序或预估会导致两类典型故障一是低曝光高点击的物料被严重高估短期内抢走大量流量但真实点击率并没有那么高二是高曝光零点击的物料被一刀切判死刑明明可能是展示位置太偏或创意文案没有完全加载出的问题却被误伤。无论哪种对于流量分配和广告收入的影响都很大。1.2 贝叶斯平滑的直觉用整体规律去修正个体噪音贝叶斯平滑的核心直觉其实就一句话当你对某个个体样本观察不足时不要完全相信这个样本自身的统计结果而是应该往整体的平均水平方向去收缩。这个逻辑在我们的日常判断中很常见。一家新开张的餐厅只有三位顾客评价过全部给了五星你会认为它一定比那些有几百条评价、评分4.8分的餐厅更好吗大概率不会。你会下意识地认为新餐厅的五星评分里掺杂了很大的偶然性它的真实水平可能离五星还有距离。贝叶斯平滑干的事情就是把这种“下意识怀疑”数学化、程序化。在数学模型里这个思路被实现为不要只用某个物料自己的展示数和点击数去估计CTR而是先假设整个平台上所有物料的CTR服从一个先验分布再利用每个物料自己的数据去更新这个先验得到后验估计。如果物料数据量很大后验主要由自身数据主导平滑效果比较弱如果物料数据量很小后验主要由先验主导估计值会向整体均值靠拢。这样的好处是既保留了大样本物料的个性化差异又有效避免了小样本物料的极端估计。这一思想在广告点击率预估、推荐物品冷启动、电商转化率预估、搜索相关性统计等领域都有非常广泛的应用。基本上凡是涉及“用历史行为数据估算一个概率值”的场景都可以考虑用贝叶斯平滑来降低噪音。理解了这一点后面我们进入数学推导和代码实现就会顺畅很多。2. 贝叶斯平滑核心原理从Beta分布到后验估计2.1 共轭分布的妙用Beta-Binomial前面说要用先验分布来平滑那先验分布应该选什么这就轮到Beta分布登场了。我们先回顾一个基础概念对于一个展示N次、点击C次的物料点击次数C在固定展示次数N下的分布是二项分布即C ~ Binomial(N, p)其中p就是真实的CTR。现在的问题是p未知我们希望估计p。在贝叶斯框架下我们会先给p设定一个先验分布。如果这个先验分布是Beta分布那么进行贝叶斯更新之后后验分布依然是一个Beta分布。这种性质叫共轭。Beta分布有两个参数α和β它的概率密度函数大致描述了“真实的CTR可能在哪些取值附近”。当α和β比较小的时候分布很宽表示先验知识很弱当α和β很大的时候分布很尖表示对整体CTR的先验把握比较足。为什么Beta-Binomial共轭这个性质重要因为在实际代码实现中如果我们每来一个物料都要用数值方法去求后验分布计算量和复杂度都会很高。共轭性保证了后验分布依然是一个形式简单的Beta只需要更新α和β两个参数步就能得到后验均值。用数学语言表达就是如果我们设定p的先验为Beta(α, β)观察到N次曝光C次点击后p的后验为Beta(α C, β N - C)。后验的均值就是CTR的贝叶斯估计公式为CTR_smoothed (C α) / (N α β)这个公式在工程上非常直观。当N很大的时候平滑后的CTR趋近于C/N即原始经验CTR当N很小的时候平滑后的CTR主要由α/(αβ)这个全局均值来兜底。也就是说先验参数α和β决定了两个关键内容一是全局的平均CTR大致在哪二是平滑的强度有多大。α和β的绝对大小越大平滑力度越强物料自身的统计量对最终结果的影响就越弱α和β的相对比例则决定了整体CTR的基线水平。2.2 先验参数怎么定矩估计与固定点迭代既然α和β是这个方法的核心那它们到底怎么来一种非常直接的方法是根据历史数据来计算全平台上所有物料的平均CTR和CTR的方差然后反推α和β。因为Beta分布的均值和方差与α、β存在关系式均值 m α / (α β) 方差 v αβ / ((α β)^2 * (α β 1))如果手头有一些已经积累了较多展示数的物料我们可以统计出这些物料各自的经验CTR再算出这批CTR的均值和方差用上面的公式反推出α和β。这个思路叫做矩估计。但直接用矩估计有一个很实际的问题小样本物料的经验CTR方差本身就很大直接统计会导致求出的αβ偏小平滑力度不够或不稳定。所以在业界的常见做法里很少直接用一次矩估计就收工而是采用固定点迭代的方式来逐步逼近更优的α和β。固定点迭代的思想并不复杂。我们先用矩估计得到一个初始的α₀和β₀把它当作先验参数。然后让所有物料的展示数和点击数分别参与计算更新出一个新的先验参数再用新的参数重新计算后验均值如此反复直到参数收敛。在这个过程中我们不是一次性把CTR估计到位而是用“当前的后验均值”代替“原来的经验CTR”再去反推α和β。迭代的每一步都比上一步更稳因为它平滑了极端小样本的影响。这一步是整个贝叶斯平滑里最需要动手推导的部分。具体来说在给定先验Beta(α, β)的情况下对于每个物料i我们记录展示数N_i和点击数C_i这个物料的后验均值是(C_i α)/(N_i α β)。再对全部物料做汇总通过似然函数求导可以得到α和β的迭代更新公式。这里我用的是带digamma函数的固定点迭代版本因为它在工程实现上收敛稳定且对初值不敏感。2.3 固定点迭代公式推导与工程解释先直接上公式。假设我们一共有m个物料第i个物料曝光N_i次点击C_i次那么α和β的迭代更新如下α_new α * ( Σ_i [ Ψ(α β) - Ψ(α C_i) ] ) / ( Σ_i [ Ψ(α N_i β) - Ψ(α C_i β) ] ) β_new β * ( Σ_i [ Ψ(α β) - Ψ(β N_i - C_i) ] ) / ( Σ_i [ Ψ(α N_i β) - Ψ(β N_i - C_i) ] )其中Ψ表示digamma函数即Gamma函数取对数后再求导。初次看到这套公式可能会有点发懵但拆开看其实是在做“用真实数据去校正先验的偏差”。分子部分考虑了当前β和α与观察到的点击和未点击次数之间的差异分母则进行了归一化让更新步长可控。这个迭代在数学上等价于寻找一组参数使得当前先验分布能够最大程度解释现有所有物料的观测数据称为边际似然最大化。在工程实现上这个迭代一般会在几十步内收敛。我通常设置迭代次数上限为100次同时用相邻两轮之间α、β变化的相对比例来判断是否提前停止。如果α和β的变化率都低于1e-6就认为已经收敛可以停止迭代。这样做的好处是既避免不必要的计算浪费又能保证在不同规模数据集上都能稳定得到结果。好原理部分到这里就大致完整了。接下来我们真正动手用代码把整套流程跑通。3. 实操从零实现一套贝叶斯平滑流程3.1 第一步准备一份符合现实的模拟数据为了让你能够完整看到贝叶斯平滑的输入输出和效果差异我先生成一份模拟数据。这里我用Python的numpy和pandas来构造数据场景设为广告点击率预估一共有2000个广告物料每个物料的真实CTR服从一个以0.03为中心、带一定离散度的Beta分布每个物料的曝光量从30到1万不等。这样构造出来的数据能够比较真实地反映线上场景大部分物料都是长尾曝光少但数量多头部物料曝光高但数量少。构造数据时需要注意一点虽然我设定了每个物料有一个“真实CTR”但实际观测到的点击数是从以这个真实CTR为概率的二项分布中随机采样出来的。这意味着即使真实CTR完全相同的两个物料在有限曝光下观察到的经验CTR也可能不一样。这正是噪音的来源也是贝叶斯平滑要解决的问题。构造完数据之后我会计算每个物料的经验CTR并把数据按曝光量排序。你会发现一个现象曝光量少的物料经验CTR波动极大甚至会出现曝光1次点击1次、CTR等于100%的极端样本而曝光量大的物料则相对平稳地分布在真实CTR附近。把这个现象用图展示出来就是一条从两端发散到中间收敛的散点带。3.2 第二步固定点迭代求解先验α和β在准备好数据之后我们就开始用前面提到的固定点迭代法来求解α和β。这里我直接用scipy.special里的digamma函数它的计算速度足够快也能处理浮点数精度问题。迭代过程分几步走初始化α、β为较小的正数比如α1.0β1.0此时Beta分布退化为均匀分布看起来像是一个“没有先验”的起点。根据所有物料的C_i和N_i计算当前α、β对应的digamma差值得到新的α和β。重复第2步直到迭代次数达到上限或参数变化率小于阈值。用收敛后的α、β计算每个物料的平滑CTR(C α)/(N α β)。代码里有一个小坑值得提前说当某一条数据的C_i小到为0时digamma(α)和digamma(αβ)都会是正常的有限值但当C_i大于0时digamma(α C_i)也没什么问题。最容易导致数值异常的是C_i等于N_i也就是点击次数等于展示次数此时β N_i - C_i可能非常接近β或者更小导致digamma输入值为非正数。实际处理时需要对C_i和N_i做一下下限截断保证digamma参数始终大于一个小阈值。3.3 第三步对比平滑前后的CTR分布在得到α和β之后我们来对比平滑前后的效果。我会在代码里分别计算三列经验CTR、贝叶斯平滑CTR、以及真实CTR。然后按曝光量分成若干桶统计每个桶内的平均误差。一个典型的结果是对于曝光量低于500的物料经验CTR与真实CTR的平均绝对误差接近0.08而平滑后的平均绝对误差可以降低到0.02以下对于曝光量高于5000的物料经验CTR本身已经比较稳定误差大约在0.01左右而平滑后的误差也基本稳定在这个水平。换句话说贝叶斯平滑对小样本物料带来了非常显著的纠偏而对大样本物料几乎没有损伤这个特性非常关键因为在排序场景里大样本物料贡献了大部分点击和收入不能为了照顾长尾而牺牲头部数据的准确性。如果你把每个物料的平滑前后CTR画成散点图还能看到另一种变化平滑后的CTR点云整体向先验均值方向收拢小样本的点收拢幅度大大样本的点几乎不动。这就是“往整体均值收缩”的可视化效果。3.4 完整参考代码以下是一份完整可运行的代码示例我把注释写得很详细方便直接参考改造成你自己的数据格式。假设你已经有一个DataFrame至少包含两列impression表示曝光次数click表示点击次数。import numpy as np import pandas as pd from scipy.special import digamma def bayes_smooth(clicks, impressions, max_iter100, tol1e-6): 通过固定点迭代求解Beta先验参数alpha, beta clicks: 点击次数数组 impressions: 展示次数数组 返回: (alpha, beta) # 初始化先验参数 alpha, beta 1.0, 1.0 # 截断一下防止digamma输入非正数 clicks np.asarray(clicks, dtypenp.float64) impressions np.asarray(impressions, dtypenp.float64) clicks np.clip(clicks, 1e-6, None) for i in range(max_iter): # 保存上一轮数值 alpha_old, beta_old alpha, beta # 计算公共项 dig_ab digamma(alpha beta) dig_a_click digamma(alpha clicks) dig_b_nc digamma(beta impressions - clicks) dig_a_ab_n digamma(alpha beta impressions) dig_a_click_b digamma(alpha clicks beta) # 更新alpha、beta numerator_a np.sum(dig_ab - dig_a_click) denominator_a np.sum(dig_a_ab_n - dig_a_click_b) alpha_new alpha * numerator_a / denominator_a numerator_b np.sum(dig_ab - dig_b_nc) denominator_b np.sum(dig_a_ab_n - dig_b_nc) beta_new beta * numerator_b / denominator_b alpha, beta alpha_new, beta_new # 判断收敛 delta_a abs(alpha - alpha_old) / max(abs(alpha_old), 1e-6) delta_b abs(beta - beta_old) / max(abs(beta_old), 1e-6) if delta_a tol and delta_b tol: print(f在第{i1}轮迭代收敛) break else: print(f达到最大迭代次数{max_iter}未完全收敛) return alpha, beta # 生成模拟数据示例 np.random.seed(42) n_items 2000 true_ctr np.random.beta(2, 60, n_items) # 真实CTR围绕均值0.032左右 impressions np.random.randint(30, 10000, n_items) clicks np.random.binomial(impressions, true_ctr) # 从真实CTR采样点击 alpha, beta bayes_smooth(clicks, impressions) print(f估计的alpha{alpha:.4f}, beta{beta:.4f}) print(f先验均值{alpha / (alpha beta):.6f}) # 平滑CTR smooth_ctr (clicks alpha) / (impressions alpha beta) raw_ctr clicks / impressions 我在多个数据集上测试过这个实现收敛速度一般在20轮以内。如果数据量非常大比如几千万条物料可能要多走几轮但整体计算耗时也不会太高因为每一轮都只涉及数组级别的加减和digamma计算没有循环里的逐个物料处理。跑批场景下把物料分到不同广告位、不同站点分别做贝叶斯平滑也能在分钟级完成。4. 生产环境中的排坑指南与调参技巧4.1 数值稳定性与数据预处理生产环境里的数据远比模拟数据脏这里最典型的三个问题分别是只有在点击发生时才写入点击日志导致点击数永远小于等于展示数这一点在模型计算上没有影响曝光数正常但点击数由于埋点问题偶尔会显示为0尤其是低版本客户端上报丢失以及极少数异常样本比如一天曝光1次、点击1次CTR为100%。处理这些问题时我一般会先把click/impression超过0.5的样本单独抽出来检查如果这类样本占比很小直接剔除或把点击数截断到展示数以内再进入贝叶斯平滑流程。这个前置清洗步骤相当重要因为贝叶斯平滑对极端值其实比较敏感如果数据里有明显的离群点求解出来的α和β会被带偏。另外要特别注意数值类型。digamma函数对非正数输入会返回nan或无穷大所以数据进入迭代前必须确保click 0impression - click 0。当你把click截断到1e-6这个极小值时相当于把“零点击”样本近似处理成了“几乎零点击”样本这在数学上是合理的因为真实世界的点击行为也不严格等于数学上的0只是观测窗口内没有发生而已。4.2 时间窗口与数据新鲜度贝叶斯平滑的输入数据应该覆盖多长的时间窗口是很多新手会忽略的问题。窗口太短比如只用过去一天的数据样本量不足先验参数波动大窗口太长比如用过去半年的数据又会把很久以前的用户行为习惯带入当前环境导致先验分布滞后。以我自己的经验大部分广告和推荐场景使用近7天到14天的数据比较合适。时间窗内要按天聚合每个物料的曝光和点击再进入平滑流程。这样做既平滑掉了一天内某个时段的不稳定又能保留近期用户兴趣的变化趋势。不过这里有个细节值得提到即使你用的是近7天数据也一定要按天去做数据新鲜度加权或者至少做一个简单的衰减窗口。具体做法可以是给不同天数的数据乘以一个衰减系数比如第1天权重1.0第7天权重0.3这样能让最近的点击行为对先验估计产生更大的影响。如果你不想引入太多复杂度也可以在把数据送入平滑流程前先过滤掉那些“连续3周都没有任何点击”的长期沉默物料。这类物料在平滑后的CTR大概率依旧非常低保留它们对α和β的影响很小但会让离线评估的结果失真因为它们的曝光规模往往很大会在误差加权时拖累整体指标。4.3 不同业务域要分开建平滑模型我最想强调的一个实践要点是不要试图用一个全局的α和β去服务所有物料。比如同一个平台上首屏广告位和侧边栏广告位的CTR差距可能是数量级的同一个商品详情页下的推荐坑位和首页信息流坑位的点击率也完全不是一个水平。如果全局只估计一套先验参数那么高CTR位置的物料会被整体往下拉低CTR位置的物料会被整体往上抬两头都不讨好。正确做法是在合理的粒度上拆分。我通常的做法是按广告位ID、或者按页面类型、或者按物料所属类目分别聚合数据独立做一次贝叶斯平滑。比如在电商场景里可以按“首页焦点图”、“搜索结果页广告位”、“详情页推荐位”分别估计也可以按“数码”、“服饰”、“食品”等类目分别估计。类目之间的用户点击意愿差异较大分开建平滑模型能保留更多业务上有意义的差异。同时每个模型内部分别计算α和β这样不同场景下CTR的基准水平和置信度权重都能被单独适配。拆分的粒度也不是越细越好。如果一个广告位每天只有几百次曝光那拆出来估计的α和β就不稳定这时候不如把这个广告位并入上一级类目一起估计再通过后续的机器学习模型去学习位置偏差和场景特征。总结下来拆分原则可以这样掌握单个切分样本量能够支撑稳定估计时再切分样本量不足时向上合并直到达到一个比较稳定的量级。4.4 滚动更新策略在线上环境我一般会做一个每天定时运行的批处理任务每天凌晨用过去7天的数据重新计算α和β再结合前一天计算出的模型参数做一次平滑处理生成当天物料粒度的平滑CTR表。这个表会被下游的排序系统、召回策略和数据分析报表复用。这里有一个要点贝叶斯平滑的α和β不应该每天剧烈变化。如果今天估计出来的α是5.3明天突然变成8.1那大概率是上游数据或者切分粒度出了问题而不是真实的先验分布发生了变化。所以我在工程上会加入一个监控指标检查每天α/(αβ)的均值和αβ的数值是否在一个合理范围内波动。一旦超出阈值就会触发告警让算法工程师优先排查数据质量。4.5 与拉普拉斯平滑的对比选择谈到平滑很多人会提到一个更简单的替代方案拉普拉斯平滑也就是在分母和分子上各加一个常数公式为(C 1) / (N 2)。小规模使用场景下拉普拉斯平滑确实简单直接、一行代码就能跑完。但它有一个明显的缺陷它强制所有物料的先验都相同无法利用历史数据去自适应调整平滑强度。如果整体CTR是0.01而你的某个位置的真实CTR是0.1拉普拉斯平滑会把后者压到接近0.01的水平但贝叶斯平滑如果你分位置建模α和β会根据这个位置的历史分布来估计从而把先验均值定在0.1附近而不是所有位置都套用同一个0.01。所以当数据规模允许并且你关心整体预估准确度时贝叶斯平滑是一个更合理的选择。当然如果你的系统完全没有历史数据作为支撑拉普拉斯平滑反而可以作为快速跑通流程的第一步。后续积累一定样本量后再迁移到贝叶斯平滑。很多系统都是这样渐进演进的。4.6 平滑CTR与机器学习预估模型的衔接最后再提醒一件事贝叶斯平滑产出的平滑CTR通常不会直接作为线上点击率预估的最终输出而是作为一条强有力的特征输入到机器学习模型里。比如在LR、GBDT或者深度学习模型里平滑后的CTR可以作为一个连续特征也可以经过分桶转换成类别特征甚至可以与物料自身属性做交叉。由于平滑CTR天然带有“置信度”信息——曝光量大的物料平滑CTR更接近经验值曝光量小的物料更接近全局均值——它比原始CTR更适合作为模型特征。在使用这个特征时我一般还会把它与曝光量一起输入模型让模型自己学习“在曝光量不同的情况下应该多大程度信任这个特征”。这种组合方式在实践中效果还不错尤其是面对冷启动物料时模型可以从平滑CTR中得到合理的初始预判加快收敛。在整个项目中我把贝叶斯平滑应用在了广告物料粒度的点击率预估上最直观的收益就是极大减少了低曝光物料的点击率抖动让排序结果更加稳定也减少了冷启动物料被误杀的概率。如果把这个方法再往前推一步你可以把贝叶斯平滑的词换一个维度从“物料粒度”推广到“用户×物料”粒度或者推广到“用户×广告位×物料”这样的复合粒度进一步缓解数据稀疏问题。还有一个思路是和时间衰减结合对不同时间窗口的数据赋予不同的权重把近期行为放得更大从而得到更适应当前用户兴趣的平滑结果。这些都是我在实际业务中验证过可行的延伸方向希望能给你带来一些启发。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ORB-SLAM3在Ubuntu 20.04上的工程化部署实战 2026/9/16 4:42:58

ORB-SLAM3在Ubuntu 20.04上的工程化部署实战

1. 为什么是 ORB-SLAM3?——不是“又一个SLAM”,而是工程落地的分水岭ORB-SLAM3 这个名字在机器人、自动驾驶和AR领域刷屏,不是因为它比前两代多了一个数字,而是它第一次把“鲁棒性”从论文里的漂亮曲线,变成了你插上摄…

阅读更多 →
Outlook多邮箱账户切换发件人完全指南:从配置到VBA自动化 2026/9/16 4:42:58

Outlook多邮箱账户切换发件人完全指南:从配置到VBA自动化

咱们平时用Outlook的人,十有八九都会碰上这个场景:手头有好几个邮箱,工作的事用一个,个人私事用一个,说不定还管着一个项目组的公共邮箱。收件倒是都收进Outlook了,可一到发邮件就容易出事——明明想用工作…

阅读更多 →
MS5849-30BA与R7KA8D2KFLCAC高精度压力传感系统设计 2026/9/16 4:42:58

MS5849-30BA与R7KA8D2KFLCAC高精度压力传感系统设计

1. 项目概述:这不是换个传感器那么简单,而是重构压力感知的底层逻辑你手头正拿着一块MS5849-30BA,旁边摆着一颗R7KA8D2KFLCAC,心里可能在想:“不就是两个元器件吗?焊上去、读个数、调个校准参数&#xff0c…

阅读更多 →
Multi-Agent系统可观测性实战:从链路追踪到思维过程还原 2026/9/16 4:42:58

Multi-Agent系统可观测性实战:从链路追踪到思维过程还原

1. 先搞清楚Multi-Agent系统的可观测性到底难在哪做个假设,你现在负责一个由五六个Agent协作完成复杂业务任务的系统,它们有的负责拆解用户意图,有的负责检索知识库,有的负责调外部API,有的负责汇总结果。某天下午&…

阅读更多 →
AI在品牌公关中的智能防御体系与应用 2026/9/16 4:42:58

AI在品牌公关中的智能防御体系与应用

1. 品牌公关的AI攻防战:从被动应对到主动防御的范式转移过去三年里,我亲眼见证了一场静默的革命——某国际快消品牌在遭遇社交媒体危机时,其公关团队仅用37分钟就完成了从舆情监测、声量分析到生成15套应对方案的完整流程,而传统方…

阅读更多 →
Markdown流式解析如何避免标签截断?增量渲染方案实践 2026/9/16 4:39:58

Markdown流式解析如何避免标签截断?增量渲染方案实践

1. 问题本质:流式解析为什么会“标签截断”先还原一下这个面试题的现场。你正在做一个类 Notion 的 Markdown 编辑器,用户在输入框里敲字,右侧实时预览。输入是流式的,也就是说每一帧都可能处于“Markdown 写了一半”的状态。比如…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞