nexusbert commited on
Commit
cf4b406
·
1 Parent(s): e02e7f2

Tune mood recos to trending Naija playlists and pre-load HF models

Browse files
Files changed (2) hide show
  1. app/main.py +33 -5
  2. app/spotify_playlist_reco.py +39 -0
app/main.py CHANGED
@@ -39,7 +39,7 @@ from .spotify_catalog_api import (
39
  search_tracks_by_artist,
40
  get_artist_top_tracks,
41
  )
42
- from .spotify_playlist_reco import recommend_playlist_for_emotion
43
 
44
 
45
  Base.metadata.create_all(bind=engine)
@@ -102,13 +102,27 @@ def mood_from_text(
102
  raise HTTPException(status_code=400, detail="Text cannot be empty")
103
 
104
  label, score = analyze_text_emotion(body.text)
105
- track = recommend_track_for_emotion(label, source="text") or {}
106
- track_id = track.get("id") if track else None
107
  try:
108
  playlist = recommend_playlist_for_emotion(label)
109
  except SpotifyAPIError:
110
  playlist = {}
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  playlist_id = playlist.get("id") if playlist else None
113
 
114
  try:
@@ -160,13 +174,27 @@ async def mood_from_face(
160
  raise HTTPException(status_code=400, detail="Invalid image file") from exc
161
 
162
  label, score = analyze_face_emotion(image)
163
- track = recommend_track_for_emotion(label, source="face") or {}
164
- track_id = track.get("id") if track else None
165
  try:
166
  playlist = recommend_playlist_for_emotion(label)
167
  except SpotifyAPIError:
168
  playlist = {}
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  playlist_id = playlist.get("id") if playlist else None
171
 
172
  try:
 
39
  search_tracks_by_artist,
40
  get_artist_top_tracks,
41
  )
42
+ from .spotify_playlist_reco import recommend_playlist_for_emotion, pick_random_track_from_playlist
43
 
44
 
45
  Base.metadata.create_all(bind=engine)
 
102
  raise HTTPException(status_code=400, detail="Text cannot be empty")
103
 
104
  label, score = analyze_text_emotion(body.text)
 
 
105
  try:
106
  playlist = recommend_playlist_for_emotion(label)
107
  except SpotifyAPIError:
108
  playlist = {}
109
 
110
+ track: dict = {}
111
+ track_id: str | None = None
112
+ try:
113
+ if playlist:
114
+ track = pick_random_track_from_playlist(
115
+ playlist_id=playlist.get("id"),
116
+ )
117
+ track_id = track.get("id") if track else None
118
+ except SpotifyAPIError:
119
+ track = {}
120
+ track_id = None
121
+
122
+ if not track_id:
123
+ track = recommend_track_for_emotion(label, source="text") or {}
124
+ track_id = track.get("id") if track else None
125
+
126
  playlist_id = playlist.get("id") if playlist else None
127
 
128
  try:
 
174
  raise HTTPException(status_code=400, detail="Invalid image file") from exc
175
 
176
  label, score = analyze_face_emotion(image)
 
 
177
  try:
178
  playlist = recommend_playlist_for_emotion(label)
179
  except SpotifyAPIError:
180
  playlist = {}
181
 
182
+ track: dict = {}
183
+ track_id: str | None = None
184
+ try:
185
+ if playlist:
186
+ track = pick_random_track_from_playlist(
187
+ playlist_id=playlist.get("id"),
188
+ )
189
+ track_id = track.get("id") if track else None
190
+ except SpotifyAPIError:
191
+ track = {}
192
+ track_id = None
193
+
194
+ if not track_id:
195
+ track = recommend_track_for_emotion(label, source="face") or {}
196
+ track_id = track.get("id") if track else None
197
+
198
  playlist_id = playlist.get("id") if playlist else None
199
 
200
  try:
app/spotify_playlist_reco.py CHANGED
@@ -49,3 +49,42 @@ def recommend_playlist_for_emotion(emotion: str, *, market: Optional[str] = None
49
  return {}
50
 
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  return {}
50
 
51
 
52
+ def pick_random_track_from_playlist(playlist_id: str, *, market: Optional[str] = None) -> Dict[str, Any]:
53
+ """
54
+ Given a playlist ID, return a random track from it (using app-only token).
55
+ This is used so mood-based suggestions come from popular Naija playlists.
56
+ """
57
+ import random
58
+
59
+ token = get_app_access_token()
60
+ mk = market or settings.spotify_market or "NG"
61
+ data = spotify_get(
62
+ f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks",
63
+ token,
64
+ params={"market": mk},
65
+ )
66
+ items = data.get("items") or []
67
+ tracks = []
68
+ for it in items:
69
+ t = (it or {}).get("track") or {}
70
+ if not t or t.get("is_local"):
71
+ continue
72
+ album = t.get("album") or {}
73
+ images = album.get("images") or []
74
+ image_url = images[0].get("url") if images else None
75
+ tracks.append(
76
+ {
77
+ "id": t.get("id"),
78
+ "name": t.get("name"),
79
+ "artists": [a.get("name") for a in (t.get("artists") or []) if isinstance(a, dict)],
80
+ "preview_url": t.get("preview_url"),
81
+ "external_url": (t.get("external_urls") or {}).get("spotify"),
82
+ "album": album.get("name"),
83
+ "image_url": image_url,
84
+ }
85
+ )
86
+ if not tracks:
87
+ return {}
88
+ return random.choice(tracks)
89
+
90
+