一个可解释、可观测且可复现的短视频信息流推荐系统。在线部分 用 9 节点异步 DAG 组织多路召回、排序、重排、曝光过滤和反馈闭环;离线部分 在快手 KuaiRand-Pure 真实日志上训练 BPR、SASRec、Shared Bottom 与 MMoE,并使用后期随机干预曝光 评测,避免把电影评分或旧推荐策略的选择偏差包装成业务效果。
项目强调可复现证据:固定随机种子、严格时间切分、随机曝光评测、配对置信 区间、自动化测试和性能门禁。它不是对生产流量或线上收益的虚构。
- 真实短视频数据:处理 1,141,112 条早期标准策略交互和 1,186,059 条 后期随机曝光交互;5,737 名合格用户固定拆为 1,147 名验证用户和 4,590 名最终测试用户,覆盖 7,583 个视频。
- 序列模型 + 多任务精排:独立实现 42.3 万参数的 2 层因果 Transformer SASRec,并以 147 维序列/候选特征训练 Shared Bottom 与 4-Expert MMoE,分别预测点击、长播、观看比例和负反馈。
- 约束式业务融合:在验证集同时设置观看比例、负反馈、多样性和非热门差异护栏,并用 Top-10 非热门配额缓解软权重的跷跷板冲突。
- 本地真实模型服务:导出 SASRec 与多任务 state dict、物品映射和 12 位未参与调参的代表性测试用户快照;FastAPI 懒加载后在 CPU 实时对比五种策略,全程不调用外部 AI API。
- 无泄漏、抗偏评测:只使用 4 月 8–21 日标准日志训练,在 4 月 22–5 月 8 日随机干预日志评测;个性化参数只在验证用户选择,最终测试用户完全不参与调参。
- 多目标指标:同时报告 AUC、nDCG、Recall、有效互动、点击、长播、观看 比例、负反馈、目录覆盖率和标签多样性。
- 在线推荐链路:新鲜、热门、兴趣、协同 4 路召回并行执行,结果包含召回 来源、推荐理由和 7 项分数解释。
- 反馈与曝光闭环:喜欢、收藏、看过、跳过和不喜欢写入 SQLite,影响下一轮兴趣 特征;近期曝光和明确负反馈进入过滤/降权逻辑。
- 可验证的演示目录:95 条确定性短视频覆盖 8 个类别,每路召回 48 条候选; 自动化测试确认连续刷新 5 页可获得 60 条完全不重复的内容。95 条内容全部使用 仓库内互不重复的确定性 SVG 封面,不依赖外部图片服务,并提供通用失败回退。
- 可观测异步 DAG:拓扑校验、最大并发、失败传播、节点耗时和请求级 Trace 均可在 Web 页面查看。
- 工程化交付:FastAPI、Pydantic、SQLite、OpenAPI、pytest、性能基准、 GitHub Actions 和 Spec Kit 规格文档。
数据:快手 KuaiRand-Pure。模型只用 4 月 8–21 日标准 Feed 训练;4 月 22 日至 5 月 8 日的随机曝光用户按稳定哈希拆成 1,147 人验证集和 4,590 人 最终测试集。验证集选择历史标签权重、热门校正和多样性约束,测试集不参与调参。
| 模型 | AUC | nDCG@10 | Recall@10 | Engagement P@10 | Click@10 | Watch Ratio@10 | Coverage@10 | Diversity@10 |
|---|---|---|---|---|---|---|---|---|
| Popularity | 0.573139 | 0.413635 | 0.502193 | 0.251547 | 0.245882 | 0.229183 | 0.839114 | 0.921085 |
| 原始 SASRec-Lite | 0.574966 | 0.417038 | 0.502560 | 0.253464 | 0.247996 | 0.231486 | 0.844257 | 0.921260 |
| 个性化增强 SASRec | 0.593031 | 0.428899 | 0.516763 | 0.259477 | 0.253834 | 0.219022 | 0.857972 | 0.881052 |
| Shared Bottom 约束重排 | 0.579625 | 0.418578 | 0.502682 | 0.253312 | 0.248061 | 0.228031 | 0.874456 | 0.914356 |
| MMoE 约束重排 | 0.582935 | 0.421314 | 0.506596 | 0.255686 | 0.250523 | 0.227656 | 0.876302 | 0.907939 |
单目标个性化 SASRec 相对 Popularity 的 nDCG@10 提升 3.69%,但 Watch
Ratio 下降 4.43%。多任务 MMoE 在观看、负反馈、多样性和非热门差异护栏内,
nDCG@10 提升 1.86%,观看比例缺口收敛到 0.67%,负反馈率下降
3.59%,Top-10 中 19.20% 的内容不同于热门榜。逐用户 nDCG 差值
95% CI 为 [0.004448, 0.010910],p = 3.18e-6。
这是可解释的 Pareto 权衡:MMoE 没有保留单目标模型的全部 nDCG 收益,但明显 恢复观看质量并提高目录覆盖与列表多样性。完整方法、公式和实验说明见 多任务精排实验。
训练与运行:
- BPR pairwise loss:
0.515860 → 0.302980(-41.27%) - SASRec sampled BCE:
0.640800 → 0.416074(-35.07%) - MMoE Head validation loss:
0.537844 → 0.532562 - 正式 Windows CPU 实验总耗时:约
75.5 s - 多任务质量门禁:nDCG 提升至少 1.5% 且 95% CI 下界大于 0、观看保留至少 99%、热门榜差异至少 15%、测试多样性至少 0.85、负反馈不劣于热门榜
flowchart LR
A["请求预处理"] --> B1["新鲜召回"]
A --> B2["热门召回"]
A --> B3["兴趣召回"]
A --> B4["协同召回"]
B1 --> C["候选合并"]
B2 --> C
B3 --> C
B4 --> C
A --> D["可解释打分"]
C --> D
D --> E["多样性重排"]
E --> F["曝光过滤与回补"]
F --> G["短视频 Feed + Trace"]
H["用户反馈"] --> I["SQLite 事件与偏好"]
I --> A
在线演示的排序公式:
score =
0.32 × profile_interest
+ 0.12 × behavior_feedback
+ 0.17 × popularity
+ 0.15 × freshness
+ 0.12 × quality
+ 0.09 × collaborative
+ 0.03 × multi_source
profile_interest 是稳定的初始画像;behavior_feedback 只来自真实点击,
按 clamp(类别反馈累计值 / 0.6, -1, 1) × 0.12 计算。一次收藏会贡献
+0.056,跳过或不喜欢会显示为红色负贡献。页面中的分数条按每项权重上限
绘制,并直接标出当前名次、总目录和剩余未曝光内容。
在线主 Feed 仍使用可解释规则展示召回、反馈和 DAG;新增的“真实模型对比实验室”则 加载离线训练产生的本地 SASRec 制品,对未参与调参的测试用户执行真实 CPU 推理。两者 数据域明确分离,不把 KuaiRand 模型伪装成认识 95 条演示内容。完整说明见 架构文档。
项目不要求会使用 PowerShell:
- 双击
setup.bat安装轻量 Web 依赖; - 双击
start.bat启动服务并自动打开浏览器; - 页面地址:http://127.0.0.1:8000;
- Swagger API:http://127.0.0.1:8000/docs。
只运行主 Feed 时不需要安装 PyTorch。要使用页面中的真实模型实验室,只需先双击一次
setup_ml.bat;仓库内的轻量服务快照可直接推理,不要求下载完整 KuaiRand 数据。
若需要从真实日志重新训练,再依次双击 run_real_data_experiment.bat 和
run_multitask_experiment.bat。
若修改了演示目录,可重新生成 64 张确定性封面:
.\.venv\Scripts\python.exe .\scripts\generate-demo-covers.py- 双击
setup_ml.bat安装 PyTorch CPU 版; - 双击
run_real_data_experiment.bat训练 SASRec 骨干; - 双击
run_multitask_experiment.bat训练 Shared Bottom/MMoE 并执行质量门禁; - 首次运行会下载 KuaiRand、校验 MD5 后再解压;
- 结果与制品分别写入
experiments/results/和artifacts/。
命令行方式:
.\scripts\setup.ps1
.\scripts\setup-ml.ps1
.\scripts\run-real-data-experiment.ps1原始 KuaiRand 数据遵循 CC BY-SA 4.0,不随本仓库提交。
.\.venv\Scripts\python.exe -m pytest -q --cov=feedforge --cov-report=term-missing
.\.venv\Scripts\python.exe .\benchmarks\benchmark_pipeline.py参考 Windows 本地结果:
| 指标 | 结果 |
|---|---|
| 自动化测试 | 42 passed |
| 核心服务代码覆盖率 | 95% |
| 4 个等延迟召回节点串行耗时 | 367.27 ms |
| 4 个等延迟召回节点并行耗时 | 94.72 ms |
| DAG 加速比 | 3.88× |
| 30 次本地推荐请求 P50 | 9.23 ms |
| 30 次本地推荐请求 P95 | 10.59 ms |
基准门禁要求 DAG 加速至少 1.8×、本地请求 P95 小于 250 ms。GitHub Actions 在 push 与 pull request 时执行基础测试、覆盖率和性能门禁;深度学习实验因 数据许可和运行成本保持为显式手动复现。
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /health |
服务健康与版本 |
| GET | /api/users |
演示用户与学习后的偏好 |
| GET | /api/feed?user_id=lin&limit=12 |
生成个性化短视频 Feed |
| POST | /api/feedback |
写入 like/save/open/skip/dislike |
| GET | /api/metrics |
延迟、多样性、曝光与互动指标 |
| GET | /api/experiment |
读取真实日志离线实验与显著性结果 |
| GET | /api/model-lab/status |
检查本地 PyTorch 与模型制品 |
| GET | /api/model-lab/users |
列出未参与调参的代表性测试用户 |
| GET | /api/model-lab/compare |
本地实时计算五种策略的 Top-K、任务预测与真实反馈 |
| GET | /api/trace/latest |
最近一次 DAG 执行链路 |
| POST | /api/reset |
恢复确定性演示数据 |
完整契约见 OpenAPI 文件。
| 来源 | FeedForge 复现或借鉴的内容 |
|---|---|
| github/spec-kit v0.12.3 | Constitution → Spec → Plan → Tasks → Implement 的规格驱动流程 |
| gorse-io/gorse v0.5.11 | 多路召回、排序、反馈、过滤、回补和链路可观测 |
| chongminggao/KuaiRand | 随机干预短视频日志、多反馈信号和抗偏评测 |
项目没有复制上述系统源码,而是在普通 CPU 环境可运行的规模上复现关键工程和实验 思想。详细映射见 调研记录。
feedforge/ FastAPI、DAG、推荐与持久化
static/ 短视频信息流演示界面
static/covers/ 95 张可复现的唯一本地封面
experiments/kuairand.py BPR、SASRec 与随机曝光评测
experiments/sasrec_artifact.py 模型结构、制品导出与安全加载
experiments/multitask.py Shared Bottom、MMoE、约束融合与消融
artifacts/kuairand-sasrec.pt 本地序列模型与服务快照
artifacts/kuairand-multitask.pt 多任务 Head 与融合配置
experiments/movielens.py 次级算法回归基准
tests/ DAG、API、推荐、数据切分与模型测试
benchmarks/ 并发和接口延迟门禁
specs/003-kuairand-sequential/ 短视频实验规格、计划与任务
docs/ 架构、数据来源与真实实验说明
.github/workflows/ 持续集成质量门禁
- 在线 Web 使用可解释规则和确定性种子内容,用于验证系统流程,不声称合成数据 证明模型效果。
- 随机曝光离线指标比标准日志回放更可信,但仍不等同于线上 CTR、留存或商业收益。
- SASRec-Lite 是便于 CPU 复现的现代序列基线,不声称达到工业 SOTA。
- SQLite 适合零依赖演示;生产环境应按负载拆分缓存、事件流和分析存储。
FeedForge 代码使用 MIT。KuaiRand 数据使用 CC BY-SA 4.0,引用和 再使用时请遵守其官方许可与署名要求。