Skip to content

Repository files navigation

MovieLens 深度个性化推荐系统

一个可本地完整运行的电影推荐项目:使用双塔模型召回候选影片,使用 DeepFM 精排,通过类型多样性重排生成最终片单。后端与算法按 online / offline / nearline / common 边界拆分,在线推理和离线训练严格分离。

功能

  • 自动下载和解析 MovieLens 1M
  • 用户最后一次正反馈时间切分,避免随机切分造成数据泄漏
  • 双塔模型学习用户和电影向量
  • DeepFM 融合用户、电影、类型、年份和召回分数
  • 热门电影冷启动、已看过滤、类型多样性重排
  • Recall@K、HitRate@K、NDCG@K 离线评估
  • 个性化推荐、相似电影、片库检索、反馈、模型状态 API
  • 电影资料馆风格的响应式 React 前端
  • SQLite 反馈持久化,模型产物版本化存储
  • Docker Compose 声明 Redis、Milvus、PostgreSQL、MinIO、etcd 等真实组件
  • 后端/前端测试和 Docker Compose

后端架构

backend/
├── online/       在线 API 请求链路:pipeline + plugin
├── offline/      离线批处理训练链路:pipeline + stages
├── nearline/     准实时画像、热榜、特征更新边界
├── common/       版本、schema、storage key、manifest 等公共协议
└── app/          FastAPI 入口和历史 import 兼容层

在线 Pipeline:

UnifiedRecall → DeepFMRank → DiversityRerank → BuildResponse
      │
      ├─ Two-Tower Recall
      └─ Popular Recall

离线 Pipeline:

LoadMovieLens → PrepareTrainingSamples → TrainTwoTower
→ TrainDeepFM → EvaluateRetrieval → PublishArtifacts

详细职责见 backend/app/README.md

系统链路

MovieLens 1M
    │
    ├─ 解析、正反馈筛选、时间切分、负采样
    │
    ├─ 双塔训练 ──> 全量电影向量 ──> Top-N 召回
    │
    └─ DeepFM 训练 ──────────────> 候选精排
                                      │
                         已看过滤 + 多样性重排
                                      │
                             FastAPI + React
                                      │
                              SQLite 用户反馈

目录

backend/online/
  pipeline/recommend.py   在线编排
  plugin/                 召回、排序、重排、响应插件
backend/offline/
  pipeline/batch_train.py 离线训练编排
  stages/                 数据、训练、评估、发布阶段
backend/nearline/         准实时更新边界
backend/common/           公共协议、storage key、release manifest
backend/app/              FastAPI、模型定义、兼容 wrapper
backend/tests/          后端测试
scripts/                下载和训练命令
frontend/               React + Vite 前端

本地启动

要求 Python 3.11+、Node.js 22+。

cd movielens_recsys
make setup
make download
make train

分别启动服务:

make api
# 新终端
make web

打开 http://localhost:5173,API 文档位于 http://localhost:8000/docs

本地端到端验收:

make build
make api
# 新终端
cd frontend/dist && python3 -m http.server 8080
# 新终端
make verify-demo

验收通过会输出推荐电影标题,证明页面入口、模型加载和推荐 API 都可用。

训练默认执行 3 个 epoch。快速验证可执行:

PYTHONPATH=backend .venv/bin/python scripts/train.py \
  --epochs 1 --batch-size 8192 --embedding-dim 16

Docker

启动在线服务和真实基础组件:

make docker-demo

打开 http://localhost:8080

脚本按工业运行边界分阶段执行:先启动 Redis/Postgres/etcd/MinIO/Milvus,再运行一次性 offline-bootstrap,最后启动 online-apifrontend 并执行端到端验收。

offline-bootstrap 会检查 data/ml-1martifacts/latest。如果缺数据会下载 MovieLens;如果缺模型会跑一轮离线训练并发布到在线存储,然后再启动 online-api

脚本会先用 alpine:3.20 做新容器启动预检。如果 Docker daemon 能响应但新容器无法启动,会快速失败并提示重启 Docker Desktop:

DOCKER_START_TIMEOUT_SECONDS=10 make docker-demo

如果 Docker Hub 拉取基础镜像很慢,可以临时调短诊断超时:

DOCKER_PULL_TIMEOUT_SECONDS=60 make docker-demo

脚本会逐个拉取 Redis/Postgres/etcd/MinIO/Milvus,超时会打印当前卡住的服务和关键日志。

也可以先单独检查 Docker daemon 是否能拉外部镜像:

make docker-pull-check

如果 docker pull alpine:3.20 超时,问题在 Docker daemon 的 registry/proxy/mirror 链路;如果 docker run --rm alpine:3.20 true 超时,问题在 Docker Desktop/daemon 的容器启动路径。两者都不是本项目 Compose 配置或推荐算法代码问题。

如果需要一次性查看 daemon、pull、start-path 和当前 Compose 状态:

make docker-doctor

启动后可以执行端到端验收:

make docker-verify

该命令会检查:

  • 前端页面可访问;
  • API /api/health 模型 ready;
  • /api/recommendations 能返回真实推荐结果。

离线训练也可以作为独立 runner 在 Compose 里执行:

docker compose --profile offline run --rm offline-runner

Compose 服务边界:

  • online-api:FastAPI 推荐服务。
  • offline-runner:离线训练批处理。
  • redis:在线画像、热门召回、物料特征和版本指针。
  • milvus:向量召回索引,在线召回优先使用,失败降级到本地模型向量。
  • postgres:版本、运行记录、反馈等元数据。
  • minio:模型、特征、报告对象存储。
  • etcd:Milvus 元数据依赖。

API 示例

curl -X POST http://localhost:8000/api/recommendations \
  -H 'Content-Type: application/json' \
  -d '{"user_id": 1, "limit": 10}'

curl 'http://localhost:8000/api/movies/search?q=matrix'

curl -X POST http://localhost:8000/api/feedback \
  -H 'Content-Type: application/json' \
  -d '{"user_id": 1, "movie_id": 1196, "rating": 5}'

主要接口:

方法 路径 用途
GET /api/health 服务和模型状态
GET /api/users 演示用户列表
POST /api/recommendations 个性化/冷启动推荐
GET /api/movies/search 按片名或类型检索
GET /api/movies/{id}/similar 相似电影
POST /api/feedback 写入用户评分
GET /api/feedback/{user_id} 用户反馈记录
GET /api/model/status 模型版本和离线指标

测试

make test
make build

后端测试使用小型合成数据覆盖数据处理、模型张量、训练收敛、评估、产物往返、召回排序和 API;不需要下载 MovieLens 数据。前端测试覆盖用户选择和推荐结果渲染。

模型说明与限制

  • MovieLens 1M 不包含海报 URL,前端使用算法生成的电影卡片封面。
  • 反馈当前仍写入 SQLite,准工业级目标应迁移到 PostgreSQL。
  • 当前代码仍可用本地 artifact 跑通;Compose 环境下离线会发布到 Redis/Milvus/Postgres/MinIO,在线召回会优先读取 Redis/Milvus,异常时降级到本地 artifact。
  • 这是准工业级工程骨架,不等同于生产环境中的特征平台、实时流处理和多机训练系统。

About

纯python实现的推荐系统,和工业级别架构一致,线上服务流程区别与大规模生产,使用python实现,方面算法同学学习了解

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages