Files
pipu-music/services/recommender/pyproject.toml
T
mrleo1nidandClaude Opus 5.5 ef29b85320
ci / api / api (push) Successful in 27s
ci / recommender / recommender (push) Successful in 1m0s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m26s
feat(rec): audio analyzer and My Wave v1 engine (M4)
- migration 00006: track features and embeddings (pgvector, HNSW),
  analysis queue filled by a trigger on new tracks, wave sessions and
  impressions, recommender profiles, model versions
- analyzer basic-1 (ADR-014): ffmpeg decode, three 30 s excerpts,
  256-d timbre/rhythm embedding, tempo by onset autocorrelation, key,
  loudness, energy, danceability, acousticness, intro length; worker
  with SKIP LOCKED claims, retries and re-analysis on version change
- wave engine v1: candidates (session/taste similarity, fresh,
  liked artists, rediscover, popular, exploration, seed), filters
  (dislikes, played in 3 h, already served), heuristic score, activity
  and mood fit from contexts.yaml with relaxing thresholds, MMR with
  one track per artist, exploration share, session vector updated by
  reactions and a change of course after three skips
- POST /internal/wave/batch with the catalog index cached in memory
  and the session kept in Redis

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 12:20:55 +03:00

51 lines
1.1 KiB
TOML

[project]
name = "pipu-rec"
version = "0.1.0"
description = "Pipu Music: recommendations and audio analysis"
requires-python = ">=3.12,<3.13"
dependencies = [
"fastapi>=0.115,<1",
"uvicorn[standard]>=0.34,<1",
"pydantic-settings>=2.9,<3",
"psycopg[binary]>=3.2,<4",
"redis>=6.2,<7",
"numpy>=2.2,<3",
"pyyaml>=6.0,<7",
]
[project.scripts]
pipu-rec = "pipu_rec.cli:main"
[dependency-groups]
dev = [
"pytest>=8.4,<9",
"httpx>=0.28,<1",
"ruff>=0.12,<1",
"mypy>=1.16,<2",
"types-pyyaml>=6.0",
]
[build-system]
requires = ["hatchling>=1.27"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["pipu_rec"]
[tool.ruff]
line-length = 110
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF"]
# Комментарии и докстринги на русском: «с», «у», «−» — не опечатки в латинице.
ignore = ["RUF001", "RUF002", "RUF003"]
[tool.mypy]
strict = true
python_version = "3.12"
plugins = ["pydantic.mypy"]
[tool.pytest.ini_options]
testpaths = ["tests"]