Skip to content

PublicClassSoomin/music-rec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AI Personal Music Recommendation Base

SQLite 기반 κ³‘Β·μ˜€λ””μ˜€ νŠΉμ„± μ €μž₯, FAISS μœ μ‚¬λ„ 검색, JWT 인증(bcrypt), FastAPI, 정적 μ›Ή UIλ₯Ό ν¬ν•¨ν•œ μŒμ•… μΆ”μ²œ μ‹œμŠ€ν…œ λ² μ΄μŠ€μž…λ‹ˆλ‹€.

ν”„λ‘œμ νŠΈ ꡬ쑰

music-rec-base/
β”œβ”€β”€ api/
β”‚   └── main.py                # FastAPI: 인증, μΆ”μ²œ/검색/μΈν„°λž™μ…˜/μ’‹μ•„μš” API
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ melon_pipeline.py      # Melon 크둀링 + YouTube λ§€μΉ­ + μ˜€λ””μ˜€ νŠΉμ„± μΆ”μΆœ
β”‚   β”œβ”€β”€ database.py            # SQLite μ΄ˆκΈ°ν™”/CRUD, interactionsΒ·μ’‹μ•„μš” 쑰회
β”‚   └── faiss_index.py         # μ˜€λ””μ˜€ νŠΉμ„± 기반 FAISS 인덱슀
β”œβ”€β”€ algorithms/
β”‚   β”œβ”€β”€ base.py                # μΆ”μ²œκΈ° μΈν„°νŽ˜μ΄μŠ€ 베이슀
β”‚   └── faiss_cbf.py           # 베이슀 μƒ˜ν”Œ: FAISS μ˜€λ””μ˜€ μœ μ‚¬λ„ + ν‚€μ›Œλ“œ 검색
β”œβ”€β”€ evaluation/
β”‚   └── metrics.py             # μΆ”μ²œ 평가 μœ ν‹Έ
β”œβ”€β”€ static/                    # μ›Ή UI (인증 게이트, ν™ˆΒ·κ²€μƒ‰Β·μ’‹μ•„μš”, ν”Œλ ˆμ΄μ–΄)
β”œβ”€β”€ utils/
β”‚   └── config.py              # ν™˜κ²½λ³€μˆ˜, JWT, μˆ˜μ§‘/μΆ”μ²œ μ„€μ •
β”œβ”€β”€ docs/                      # νŒ€μž₯ 둜컬 λ¬Έμ„œ (Git μ œμ™Έ β€” `.gitignore`의 `docs/`)
β”œβ”€β”€ requirements.txt
└── README.md

μš”κ΅¬ ν™˜κ²½

  • Python 3.11 ꢌμž₯
  • macOS/Linux κΈ°μ€€ λͺ…λ Ήμ–΄
  • ffmpeg μ„€μΉ˜ ꢌμž₯ (yt-dlp μ˜€λ””μ˜€ ν›„μ²˜λ¦¬μ— ν•„μš”)

μ„€μΉ˜

cd music-rec-base
python3.11 -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -U pip setuptools wheel
pip install -r requirements.txt

μ°Έκ³ : scikit-surpriseλŠ” 일뢀 macOS ν™˜κ²½μ—μ„œ λΉŒλ“œ μ΄μŠˆκ°€ μžˆμ–΄ κΈ°λ³Έ μ˜μ‘΄μ„±μ—μ„œ λΆ„λ¦¬λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. ν•„μš” μ‹œμ—λ§Œ μˆ˜λ™ μ„€μΉ˜ν•˜μ„Έμš”.

pip install scikit-surprise==1.1.4

ν™˜κ²½λ³€μˆ˜ μ„€μ •

ν…œν”Œλ¦Ώ .env.example 을 볡사해 .env λ₯Ό λ§Œλ“  λ’€ 값을 μ±„μš°μ„Έμš”.

cp .env.example .env
DB_PATH=./music_rec.db
JWT_SECRET=κ°•ν•œ_랜덀_λ¬Έμžμ—΄λ‘œ_λ³€κ²½
JWT_EXPIRE_HOURS=24

# 선택
# GEMINI_API_KEY=
# YOUTUBE_API_KEY=
λ³€μˆ˜ μ„€λͺ…
DB_PATH SQLite 파일 경둜 (기본 ./music_rec.db)
JWT_SECRET JWT μ„œλͺ… ν‚€. 둜컬 기본값은 κ°œλ°œμš©μ΄λ―€λ‘œ 배포 μ „ λ°˜λ“œμ‹œ λ³€κ²½
JWT_EXPIRE_HOURS μ•‘μ„ΈμŠ€ 토큰 만료 μ‹œκ°„(μ‹œκ°„ λ‹¨μœ„)
GEMINI_API_KEY LangChain/LangGraphΒ·Gemini 연동 μ‹œ
YOUTUBE_API_KEY YouTube Data API μ‚¬μš© μ‹œ

데이터 μˆ˜μ§‘ νŒŒμ΄ν”„λΌμΈ

Melon 기반 톡합 νŒŒμ΄ν”„λΌμΈ

python data/melon_pipeline.py
  • 멜둠 μ—¬λŸ¬ 차트 (κΈ°λ³Έ: TOP100, HOT100, 일간, μ£Όκ°„) + μž₯λ₯΄λ³„ 곑 λͺ©λ‘ (νŽ˜μ΄μ§•, 곑 μˆ˜λŠ” utils/config.pyμ—μ„œ 쑰절)
  • (선택) **MELON_EXTRA_SONG_PAGE_URLS** β€” ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈ λ“± 곑 리슀트 URL. HTML이 μ°¨νŠΈν˜•(lst50)μ΄κ±°λ‚˜ μž₯λ₯΄ν˜•(wrap_song_info)일 λ•Œλ§Œ νŒŒμ‹±λ©λ‹ˆλ‹€ (JS μ „μš© νŽ˜μ΄μ§€λŠ” μ‹€νŒ¨ν•  수 있음).
  • μ†ŒμŠ€λ₯Ό ν•©μΉœ λ’€ 제λͺ©+κ°€μˆ˜ κΈ°μ€€ 쀑볡 제거 β†’ yt-dlp둜 YouTube λ§€μΉ­
  • μ˜€λ””μ˜€ λ‹€μš΄λ‘œλ“œ ν›„ librosa νŠΉμ„±(MFCC, BPM, energy λ“±) μΆ”μΆœ
  • songs + audio_features λ™μ‹œ μ €μž₯, μž„μ‹œ μ˜€λ””μ˜€ 파일 μ¦‰μ‹œ μ‚­μ œ

곑 μˆ˜Β·μ†ŒμŠ€λŠ” utils/config.py의 MELON_CHART_URLS, MELON_MAX_SONGS_PER_CHART, MELON_GENRE_CODES, MELON_MAX_SONGS_PER_GENRE둜 μ‘°μ •ν•©λ‹ˆλ‹€.

YouTube Data API v3둜 λ©”νƒ€λ§Œ λͺ¨μœΌλŠ” λͺ¨λ“ˆμ΄ ν•„μš”ν•˜λ©΄ νŒ€μ—μ„œ 별도 νŒŒμΌμ„ 두면 λ©λ‹ˆλ‹€. requirements.txt의 google-api-python-clientλŠ” 그런 ν™•μž₯μš©μž…λ‹ˆλ‹€.

API μ‹€ν–‰

uvicorn api.main:app --reload

λΈŒλΌμš°μ €μ—μ„œ http://localhost:8000 접속.

μ•± μ‹œμž‘ μ‹œ λ™μž‘:

  • DB μ΄ˆκΈ°ν™” 및 곑 데이터 λ‘œλ“œ
  • MusicFaissIndex 인덱슀 μΊμ‹œ λ‘œλ“œ λ˜λŠ” μž¬κ΅¬μΆ• (μ‹€νŒ¨ν•΄λ„ 곑 API 등은 기동 μœ μ§€)
  • FAISSκ°€ 정상 λΉŒλ“œλ˜λ©΄ **faiss_cbf** μƒ˜ν”Œ μ•Œκ³ λ¦¬μ¦˜μ΄ recommenders에 μžλ™ λ“±λ‘λ©λ‹ˆλ‹€.

startup()μ—μ„œ FAISS λ„˜κΈ°κΈ°

MusicFaissIndex μΈμŠ€ν„΄μŠ€λŠ” **startup()의 try 블둝 μ•ˆ**μ—μ„œλ§Œ μƒμ„±λ©λ‹ˆλ‹€. νŒ€ μ•Œκ³ λ¦¬μ¦˜μ„ 등둝할 λ•ŒλŠ” 같은 ν•¨μˆ˜ μ•ˆμ—μ„œ 방금 λ§Œλ“  faiss_index λ³€μˆ˜λ₯Ό μƒμ„±μžμ— λ„˜κΈ°λ©΄ λ©λ‹ˆλ‹€. λ‘œμ§μ„ λ‹€λ₯Έ ν•¨μˆ˜λ‘œ λΉΌλ©΄ 인자둜 μ „λ‹¬ν•˜κ±°λ‚˜, λͺ¨λ“ˆ μ „μ—­(예: app.state)에 λ³΄κ΄€ν•˜λŠ” μ‹μœΌλ‘œ μ°Έμ‘°λ₯Ό μœ μ§€ν•˜μ„Έμš”.

μ£Όμš” API

λ©”μ„œλ“œ 경둜 인증 μ„€λͺ…
POST /api/signup β€” νšŒμ›κ°€μž… β†’ access_token
POST /api/login β€” 둜그인 β†’ access_token
GET /api/me Bearer ν˜„μž¬ μ‚¬μš©μžλͺ…
GET /api/likes Bearer DB κΈ°μ€€ μ’‹μ•„μš” 곑 λͺ©λ‘
GET /api/songs β€” ?limit=30&genre=...
GET /api/songs/{song_id} β€” 곑 상세
POST /api/recommend β€” 곑 기반 μΆ”μ²œ
POST /api/recommend/user Bearer μœ μ € 기반 μΆ”μ²œ
POST /api/search β€” μžμ—°μ–΄ 검색 (search_by_query κ΅¬ν˜„ μ‹œ)
POST /api/interact Bearer play / like / skip / unlike
GET /api/algorithms β€” { "algorithms": [...] } Β· λΉ„μ–΄ 있으면 notice μ•ˆλ‚΄ 문ꡬ 포함

보호된 μ—”λ“œν¬μΈνŠΈλŠ” 헀더에 Authorization: Bearer <access_token>을 λΆ™μž…λ‹ˆλ‹€.

FAISSκ°€ λΉ„μ–΄ μžˆκ±°λ‚˜ μ΄ˆκΈ°ν™”μ— μ‹€νŒ¨ν•˜λ©΄ recommendersκ°€ λΉ„μ–΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ•ŒλŠ” μ‚¬μ΄λ“œλ°”μ— μ•ˆλ‚΄κ°€ ν‘œμ‹œλ˜κ³ , GET /api/algorithms μ‘λ‹΅μ˜ noticeλ₯Ό μ°Έκ³ ν•˜λ©΄ λ©λ‹ˆλ‹€.

μ›Ή UI

  • 둜그인/νšŒμ›κ°€μž… ν›„ 토큰은 λΈŒλΌμš°μ € localStorage에 μ €μž₯λ©λ‹ˆλ‹€.
  • μ•Œκ³ λ¦¬μ¦˜ 0개일 λ•Œ μ‚¬μ΄λ“œλ°”μ— νšŒμƒ‰ μ•ˆλ‚΄ 문ꡬ가 λ‚˜μ˜΅λ‹ˆλ‹€.
  • ν™ˆ: μΆ”μ²œ μ΅œλŒ€ 3곑 κ·Έλ¦¬λ“œ + 같은 ν™”λ©΄μ˜ 검색창(별도 검색 νƒ­ μ—†μŒ).
  • μ’‹μ•„μš”: μ„œλ²„ interactions에 μ €μž₯되며, μƒˆλ‘œκ³ μΉ¨ μ‹œ GET /api/likes둜 λ³΅μ›λ©λ‹ˆλ‹€.

DB 확인

sqlite3 music_rec.db
.tables
.schema
SELECT * FROM songs LIMIT 10;

μ•Œκ³ λ¦¬μ¦˜ 개발 λ©”λͺ¨

  • algorithms/base.py 기반으둜 μΆ”μ²œκΈ° κ΅¬ν˜„ (fit 끝에 self.is_fitted = True)
  • μ°Έκ³  κ΅¬ν˜„: algorithms/faiss_cbf.py (FaissContentRecommender)
  • fit(...), recommend(...) μΈν„°νŽ˜μ΄μŠ€ μ€€μˆ˜
  • μœ μ € 맞좀이 ν•„μš”ν•˜λ©΄ recommend_for_user(user_id, top_k) κ΅¬ν˜„
  • μžμ—°μ–΄ 검색이 ν•„μš”ν•˜λ©΄ search_by_query(query, top_k) κ΅¬ν˜„
  • λ°˜ν™˜ 포맷은 {song_id: score} λ”•μ…”λ„ˆλ¦¬ ꢌμž₯
  • api/main.py의 startup()μ—μ„œ μΈμŠ€ν„΄μŠ€ μƒμ„±Β·ν•™μŠ΅Β·recommenders["ν‚€"] 등둝

μΆ”κ°€ λ¬Έμ„œ (둜컬)

  • docs/project-overview.md β€” κΈ°νšΒ·μ—­ν•  λΆ„λ‹΄
  • docs/team-faq.md β€” μ‹€ν–‰Β·μ½”λ“œ Q&A

docs/ λŠ” νŒ€μž₯ 둜컬 ν™•μΈμš©μœΌλ‘œ .gitignore에 두어 Git에 ν¬ν•¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. νŒ€μ›μ—κ²ŒλŠ” ν•„μš” μ‹œ νŒŒμΌμ„ λ”°λ‘œ κ³΅μœ ν•˜μ„Έμš”.

About

🎡 AI-powered music recommendation system using Melon Top 100, YouTube, and LangGraph

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors