Skip to content

Commit 82e2a8d

Browse files
SimplicityGuyclaude
andcommitted
fix: resolve Discovery service errors for UI functionality
- Fix Pydantic validation error by making release_title optional in RecommendationResult - Add numpy array serialization to handle Plotly chart data in analytics responses - Remove empty string defaults to properly handle None values in recommendations These changes ensure the Discovery UI can properly handle API responses even when data is missing or when analytics charts contain numpy arrays. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 8ed4110 commit 82e2a8d

2 files changed

Lines changed: 25 additions & 11 deletions

File tree

discovery/analytics.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from datetime import datetime
55
from typing import Any
66

7+
import numpy as np
78
import pandas as pd
89
import plotly.express as px
910
import plotly.graph_objects as go
@@ -16,6 +17,19 @@
1617
logger = logging.getLogger(__name__)
1718

1819

20+
def convert_numpy_to_json_serializable(obj: Any) -> Any:
21+
"""Convert numpy arrays and other non-serializable objects to JSON-serializable format."""
22+
if isinstance(obj, np.ndarray):
23+
return obj.tolist()
24+
elif isinstance(obj, np.integer | np.floating):
25+
return obj.item()
26+
elif isinstance(obj, dict):
27+
return {key: convert_numpy_to_json_serializable(value) for key, value in obj.items()}
28+
elif isinstance(obj, list):
29+
return [convert_numpy_to_json_serializable(item) for item in obj]
30+
return obj
31+
32+
1933
class AnalyticsRequest(BaseModel):
2034
"""Request model for analytics queries."""
2135

@@ -151,7 +165,7 @@ async def analyze_genre_trends(self, time_range: tuple[int, int] | None = None)
151165

152166
return AnalyticsResult(
153167
chart_type="line",
154-
chart_data=fig.to_dict(),
168+
chart_data=convert_numpy_to_json_serializable(fig.to_dict()),
155169
insights=insights,
156170
metadata={
157171
"time_range": (start_year, end_year),
@@ -279,7 +293,7 @@ async def analyze_artist_evolution(self, artist_name: str) -> AnalyticsResult:
279293

280294
return AnalyticsResult(
281295
chart_type="scatter",
282-
chart_data=fig.to_dict(),
296+
chart_data=convert_numpy_to_json_serializable(fig.to_dict()),
283297
insights=insights,
284298
metadata={
285299
"artist": artist_name,
@@ -388,7 +402,7 @@ async def analyze_label_insights(self, label_name: str | None = None) -> Analyti
388402

389403
return AnalyticsResult(
390404
chart_type="bar",
391-
chart_data=fig.to_dict(),
405+
chart_data=convert_numpy_to_json_serializable(fig.to_dict()),
392406
insights=insights,
393407
metadata={"label": label_name, "total_records": len(label_data)},
394408
)
@@ -499,7 +513,7 @@ async def analyze_market_trends(self, analysis_focus: str = "format") -> Analyti
499513

500514
return AnalyticsResult(
501515
chart_type="area" if analysis_focus == "format" else "line",
502-
chart_data=fig.to_dict(),
516+
chart_data=convert_numpy_to_json_serializable(fig.to_dict()),
503517
insights=insights,
504518
metadata={"focus": analysis_focus, "total_records": len(market_data)},
505519
)

discovery/recommender.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class RecommendationResult(BaseModel):
4444
"""Result model for music recommendations."""
4545

4646
artist_name: str
47-
release_title: str
48-
year: int | None
49-
genres: list[str]
47+
release_title: str | None = None
48+
year: int | None = None
49+
genres: list[str] = []
5050
similarity_score: float
5151
explanation: str
5252
neo4j_id: str
@@ -203,7 +203,7 @@ async def get_similar_artists(self, artist_name: str, limit: int = 10) -> list[R
203203
recommendations.append(
204204
RecommendationResult(
205205
artist_name=similar_artist,
206-
release_title=artist_info.get("recent_release", ""),
206+
release_title=artist_info.get("recent_release"),
207207
year=artist_info.get("recent_year"),
208208
genres=artist_info.get("genres", []),
209209
similarity_score=score,
@@ -233,7 +233,7 @@ async def get_similar_artists(self, artist_name: str, limit: int = 10) -> list[R
233233
recommendations.append(
234234
RecommendationResult(
235235
artist_name=similar_artist,
236-
release_title=artist_info.get("recent_release", ""),
236+
release_title=artist_info.get("recent_release"),
237237
year=artist_info.get("recent_year"),
238238
genres=artist_info.get("genres", []),
239239
similarity_score=float(score),
@@ -282,7 +282,7 @@ async def get_trending_music(self, genres: list[str] | None = None, limit: int =
282282
trending.append(
283283
RecommendationResult(
284284
artist_name=record["name"],
285-
release_title=record["recent_release"] or "",
285+
release_title=record["recent_release"],
286286
year=record["recent_year"],
287287
genres=record["genres"] or [],
288288
similarity_score=float(record["release_count"]) / 100.0, # Normalize to 0-1
@@ -316,7 +316,7 @@ async def discovery_search(self, query: str, limit: int = 10) -> list[Recommenda
316316
results.append(
317317
RecommendationResult(
318318
artist_name=artist_name,
319-
release_title=artist_info.get("recent_release", ""),
319+
release_title=artist_info.get("recent_release"),
320320
year=artist_info.get("recent_year"),
321321
genres=artist_info.get("genres", []),
322322
similarity_score=float(score),

0 commit comments

Comments
 (0)