HAOVP 的推荐服务已经有了第一版实现。它没有使用机器学习模型,也没有依赖 Spark 之类的数据处理平台,而是从平台当前能够获得的数据出发,把用户行为、标签兴趣、视频相似度和热门内容组合起来。
这样的第一版更容易解释:一条推荐为什么出现,可以追溯到用户近期行为、内容标签、视频分类或热门分数。它的能力有限,但每一部分都可以单独验证。
推荐服务需要哪些输入
当前可以使用的信号主要有四类:
- 用户对视频产生的浏览、点赞、收藏、评论、分享和完整观看行为;
- 视频所属的标签和分类;
- 用户近期行为形成的标签兴趣;
- 一段时间内累计的热门分数。
一条简化的数据链路是:
用户行为
-> 行为记录
-> 标签兴趣 / 热门分数
-> 候选视频
-> 去重与补位
-> 首页、相似或标签推荐推荐服务不负责保存视频详情。它通过内容服务取得视频、分类和标签信息,再把推荐结果映射为前端需要的结构。
行为权重表达信号强弱
浏览一次和收藏一次表达的兴趣强度不同。第一版在记录行为时,为不同类型设置了不同权重。
可以把热门分数抽象为:
score(video) = Σ 行为次数 × 行为权重例如浏览是较弱信号,点赞、收藏和完整观看可以设置为更强信号。具体数值只是当前规则参数,不代表经过实验得到的最优值。
当前实现还按不同时间窗口生成热门内容:
最近一天 -> 日榜
最近七天 -> 周榜
最近三十天 -> 月榜首页需要热门内容时,先取较短周期的数据,不足再由更长周期补充。这个策略可以给新近内容机会,也能在当天行为数据不足时保留结果。
标签兴趣是怎样形成的
用户行为发生后,推荐服务会统计近期行为涉及的标签,再把各标签出现次数除以总次数,得到一组归一化兴趣。
某标签兴趣权重 = 近期涉及该标签的行为次数 / 所有标签行为次数假设一段时间内得到以下计数:
Java 5
数据库 3
容器部署 2
总计 10归一化后分别是 0.5、0.3 和 0.2。这些数字是解释算法的通用示例,不是 HAOVP 的真实用户数据。
这里需要区分两类权重:
- 行为权重用于区分浏览、点赞、收藏等信号,并参与热门分数计算;
- 标签兴趣在当前实现中按近期行为次数归一化。
也就是说,当前代码没有直接把每条行为的行为权重累加到标签兴趣中。文章标题里的“行为权重”和“标签兴趣”是两条相关但不同的计算链路,不能把它们写成一个已经统一训练过的模型。
标签兴趣怎样变成候选视频
有兴趣标签时,第一版会按标签权重扩充候选标签池。权重越高的标签,在候选池中出现的机会越多,再通过打乱顺序避免结果完全固定。
一个简化示例:
for (TagInterest interest : interests) {
int quota = Math.round(interest.weight() * 10);
for (int i = 0; i < quota; i++) {
candidateTags.add(interest.tagId());
}
}
Collections.shuffle(candidateTags);这是按当前思路整理的脱敏示例,不是仓库源码原样复制。
服务随后按标签向内容服务查询视频,并使用集合过滤已经加入结果的内容。这里的“权重”主要影响候选机会,并不等于最终推荐概率经过严格校准。
没有兴趣数据时怎么办
新用户或游客没有足够行为,无法立即得到稳定的标签兴趣。如果此时强行个性化,只会制造没有依据的结果。
第一版采用分层回退:
有标签兴趣
-> 按兴趣标签选择内容
没有标签兴趣,但有近期行为
-> 查找近期行为视频的相似内容
没有可用行为
-> 使用热门内容个性化结果数量不足时,也由热门内容补位。这样至少保证页面有内容,同时把“个性化推荐”和“热门兜底”区分开。
视频相似度如何计算
第一版的视频相似度使用标签和分类,不分析标题语义、画面、音频或用户向量。
标签部分使用 Jaccard 相似度:
标签相似度 = 两个视频共有标签数 / 两个视频全部不同标签数例如:
视频 A 标签:Java、Spring、MySQL
视频 B 标签:Java、Spring、Redis
交集:Java、Spring,共 2 个
并集:Java、Spring、MySQL、Redis,共 4 个
标签相似度 = 2 / 4 = 0.5这仍是通用演算示例,不对应真实视频和标签。
分类部分更简单:同分类记为相似,不同分类记为不相似。当前综合规则可以写成:
综合相似度 = 标签相似度 × 0.7 + 分类相似度 × 0.3只保存超过当前阈值的相似关系。权重和阈值是第一版规则,需要根据内容数量、标签质量和实际结果继续调整,不能把它们写成普遍适用的最佳参数。
为什么预先保存相似关系
如果每次打开视频详情页,都临时把当前视频和全部视频两两比较,数据量增加后会产生大量重复计算。
第一版使用定时任务计算相似关系并保存:
定时读取视频与标签
-> 两两计算标签和分类相似度
-> 过滤低于阈值的组合
-> 保存双向相似关系
-> 查询时按分数取前若干条这样在线查询只需要读取已经计算的结果,再到内容服务获取视频详情。
不过两两比较的计算量会随着视频数量快速增加。当前任务还只处理有限范围内的视频,所以它适合第一版和当前规模,不能直接推导为大规模推荐系统方案。
首页为什么组合多种策略
只用兴趣标签容易让内容越来越单一,只用热门内容又无法体现用户差异。当前首页按页面位置组合基于内容的推荐与热门推荐,并在个性化结果不足时补充热门内容。
可以把目标理解为:
- 兴趣标签负责相关性;
- 视频相似度负责从近期行为继续扩展;
- 热门策略负责冷启动和结果补位;
- 去重负责避免同一视频反复出现;
- 不同页面使用不同组合,增加一定多样性。
这是一种规则编排,不是经过在线实验验证的排序模型。页面轮换也不等于真正解决了信息茧房,只是第一版中控制单一结果的一种简单办法。
推荐理由也应该可解释
第一版会给结果设置简单原因,例如“热门推荐”“根据观看历史推荐”或“根据某个标签兴趣推荐”。
推荐理由必须来自真实使用的策略。如果结果实际来自热门补位,就不应该显示成“猜你喜欢”;如果只依据共同标签,也不应该声称系统理解了视频语义。
可解释性有两个作用:
- 用户能够大致理解内容为什么出现;
- 开发时可以判断某条结果来自哪条策略,便于排查空结果、重复内容和错误标签。
第一版需要验证什么
我会先验证规则是否按设计执行,而不是直接评价“推荐准不准”。
行为与兴趣
- 各类行为是否被正确记录;
- 重复上报是否会放大分数;
- 近期时间窗口是否生效;
- 标签计数和归一化结果是否正确;
- 删除或下架视频后,历史行为如何处理。
相似度
- 无标签、单标签和完全相同标签能否正确计算;
- 同分类加分是否符合预期;
- 相似关系是否双向保存;
- 定时任务重复执行是否产生重复记录;
- 视频或标签变化后旧结果是否被更新。
推荐结果
- 游客是否得到热门内容;
- 新用户是否能正常回退;
- 个性化结果不足时是否补位;
- 已加入结果的视频是否去重;
- 内容服务不可用时是否返回可解释的失败或空结果;
- 推荐理由是否和实际策略一致。
这些检查能证明代码路径和数据关系是否正确,但不能证明推荐效果已经成熟。
第一版的边界
当前实现可以确认的是:推荐服务使用行为规则、近期标签兴趣、标签与分类相似度以及热门策略组织结果。
当前不能据此宣称:
- 使用了机器学习或深度学习模型;
- 建立了成熟的用户画像;
- 使用了协同过滤、向量检索或实时特征平台;
- 已通过 A/B 测试证明效果提升;
- 已在大规模数据和高并发条件下验证;
- 当前参数是最优权重。
推荐系统第一版的价值,是先把行为、兴趣、相似内容和热门兜底串成一条可运行、可解释、可检查的链路。等数据积累和验证方法更完整,再决定哪些规则值得保留,哪些部分需要更合适的算法。