跳至内容

0010 用视频质量分决定同组菜谱的先后 ​

  • 状态:已采纳
  • 日期:2026-10-21

背景 ​

  • 推荐按「缺几样食材 → 是不是大杂烩 → 用上几样已选食材」排序,这几项都一样时按 recipe.csv 的行号排。行号只是录入顺序,跟菜好不好做、视频好不好看无关。
  • 同组的菜往往很多:选「番茄、鸡蛋」时,一样不缺的有 57 道,用户只看得到前几道。
  • 视频质量差别很大:有的几百万播放、讲得细,有的几千播放、画面也不清楚。每周的视频巡检本来就要调 B 站接口,顺手就能拿到播放、点赞、收藏、投币和时长。

方案对比 ​

问题方案取舍
分数用在哪和食材匹配度加权混合高分但缺食材的菜会排到前面,违背「按现有食材做菜」
只替换最后一级的行号不影响匹配结果和分组,只决定同组先后,风险最小
怎么算只看播放量老视频、热门 UP 主一直霸榜,播放量还会自我强化
互动率为主,播放量取对数为辅点赞、收藏、投币占播放的比例更能说明「讲得好、有人照做」
在哪算Web 和 iOS 运行时各自算两边公式要逐行对齐,浮点误差可能让顺序不一致
pnpm convert 算好写成整数 score两端只比较整数,共享用例能保证顺序完全一致
数据存哪手填进 recipe.csv每周都变,手填不现实,还会污染 CSV 的 diff
单独的 packages/data/video-stats.json每个视频一行,由脚本生成,diff 好读

决定 ​

  • pnpm check:videos --stats 在巡检的同时把每个视频的 view、like、favorite、coin、duration 写进 packages/data/video-stats.json;失效的记 { "dead": true };这次没查到(限流、超时)的沿用上次的数据。
  • 分数(packages/cook/src/utils/score.ts)是 0~100 的整数:
    • 互动率 =(点赞 + 收藏 + 投币)÷ 播放,15% 及以上算满,占 6 成;
    • 播放量取 log10,1 千记 0、1 千万记满,占 4 成;
    • 超过 15 分钟的视频扣 10 分,跟着做不方便;
    • 视频失效记 0 分;只有图文、或还没有数据的菜不写分数,排序时按 50 分算,不吃亏也不占便宜。
  • pnpm convert 和 pnpm fixtures 读这份数据,把 score 写进 recipe.json。TS 的 recommendRecipes 和 CookCore 的 Recommender 在用上的食材数相同时按分数从高到低排,分数也相同时才看行号。
  • score 是可选字段,旧版 App 解码时会忽略,不需要提高 DATA_SCHEMA_VERSION。

影响 ​

  • 更新分数:本地(或能访问 B 站的机器上)运行 pnpm check:videos --stats && pnpm convert && pnpm fixtures,一起提交。GitHub Actions 的机房 IP 常被 B 站风控,先不在 workflow 里自动提交。
  • 搜索(searchRecipes)和随机推荐暂不使用分数。
  • 下一步可以接入应用内信号:收藏数、「视频打不开 / 视频不对」的反馈直接扣分;点开率要先按结果位置纠偏(排在前面的天然点得多),等数据量够了再加。
  • 权重是拍脑袋定的初值。有了 pnpm eval:search 的评测数据后,按命中率和 MRR 调整,调整时更新这篇记录。