fix(music-lab): market API 타입 강화·ANTHROPIC_API_KEY call-time·HTTP 레이어 테스트 추가

This commit is contained in:
2026-05-01 12:32:24 +09:00
parent 26b9eea0dc
commit 355667cf9c
3 changed files with 69 additions and 8 deletions

View File

@@ -2,8 +2,8 @@ import json
import os import os
import shutil import shutil
import uuid import uuid
from typing import List, Optional from typing import Any, Dict, List, Optional
from fastapi import FastAPI, HTTPException, BackgroundTasks from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel from pydantic import BaseModel
@@ -819,7 +819,7 @@ def remove_revenue(record_id: int):
# ── 시장 조사 API ───────────────────────────────────────────────────────────── # ── 시장 조사 API ─────────────────────────────────────────────────────────────
class MarketIngestRequest(BaseModel): class MarketIngestRequest(BaseModel):
trends: list trends: List[Dict[str, Any]]
report_date: str = "" report_date: str = ""
@@ -837,7 +837,7 @@ def list_market_trends(
country: Optional[str] = None, country: Optional[str] = None,
genre: Optional[str] = None, genre: Optional[str] = None,
source: Optional[str] = None, source: Optional[str] = None,
days: int = 7, days: int = Query(7, ge=1),
): ):
return {"trends": _get_market_trends(country, genre, source, days)} return {"trends": _get_market_trends(country, genre, source, days)}

View File

@@ -8,8 +8,6 @@ from .db import (
insert_market_trends, upsert_trend_report, insert_market_trends, upsert_trend_report,
) )
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY", "")
GENRE_PROMPTS: Dict[str, str] = { GENRE_PROMPTS: Dict[str, str] = {
"lo-fi": "lo-fi hip hop, chill, relaxing beats, study music, 85 BPM, jazzy chords", "lo-fi": "lo-fi hip hop, chill, relaxing beats, study music, 85 BPM, jazzy chords",
"phonk": "dark phonk, aggressive 808 bass, Memphis trap, distorted synths, 140 BPM", "phonk": "dark phonk, aggressive 808 bass, Memphis trap, distorted synths, 140 BPM",
@@ -71,14 +69,15 @@ def _build_report(trends: List[Dict[str, Any]], report_date: str) -> Dict[str, A
def _generate_insights(top_genres: list, top_keywords: list) -> str: def _generate_insights(top_genres: list, top_keywords: list) -> str:
api_key = os.getenv("ANTHROPIC_API_KEY", "")
if not top_genres: if not top_genres:
return "아직 수집된 트렌드 데이터가 없습니다." return "아직 수집된 트렌드 데이터가 없습니다."
if not ANTHROPIC_API_KEY: if not api_key:
names = ", ".join(g["genre"] for g in top_genres[:3]) names = ", ".join(g["genre"] for g in top_genres[:3])
return f"이번 주 인기 장르: {names}. 해당 장르 중심 제작을 추천합니다." return f"이번 주 인기 장르: {names}. 해당 장르 중심 제작을 추천합니다."
import anthropic import anthropic
client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY) client = anthropic.Anthropic(api_key=api_key)
genre_str = ", ".join(f"{g['genre']}({g['score']:.1f})" for g in top_genres[:5]) genre_str = ", ".join(f"{g['genre']}({g['score']:.1f})" for g in top_genres[:5])
kw_str = ", ".join(top_keywords[:10]) kw_str = ", ".join(top_keywords[:10])
try: try:

View File

@@ -35,3 +35,65 @@ def test_ingest_idempotent(tmp_db):
reports = get_trend_reports() reports = get_trend_reports()
assert len([r for r in reports if r["report_date"] == "2026-05-01"]) == 1 assert len([r for r in reports if r["report_date"] == "2026-05-01"]) == 1
from fastapi.testclient import TestClient
def test_market_endpoints_empty(tmp_db):
"""Empty DB: /report/latest returns 404, /suggest returns []."""
from app.db import init_db
init_db()
from app.main import app
client = TestClient(app)
resp = client.get("/api/music/market/report/latest")
assert resp.status_code == 404
resp = client.get("/api/music/market/suggest")
assert resp.status_code == 200
assert resp.json()["suggestions"] == []
def test_market_ingest_endpoint(tmp_db):
"""POST /ingest returns ok, GET /report/latest returns report, GET /trends returns data."""
from app.db import init_db
init_db()
from app.main import app
client = TestClient(app)
payload = {
"trends": [
{"source": "youtube", "country": "BR", "genre": "lo-fi",
"keyword": "lofi", "score": 0.9, "rank": 1, "metadata": {}},
],
"report_date": "2026-05-01",
}
resp = client.post("/api/music/market/ingest", json=payload)
assert resp.status_code == 200
data = resp.json()
assert data["ok"] is True
assert data["trends_saved"] == 1
assert data["report_date"] == "2026-05-01"
resp = client.get("/api/music/market/report/latest")
assert resp.status_code == 200
assert resp.json()["report_date"] == "2026-05-01"
resp = client.get("/api/music/market/trends")
assert resp.status_code == 200
assert len(resp.json()["trends"]) == 1
def test_ingest_empty_trends(tmp_db):
"""Empty trends list ingests without error and returns a well-formed report."""
from app.db import init_db
from app.market import ingest_trends
init_db()
report = ingest_trends([], "2026-05-02")
assert report["report_date"] == "2026-05-02"
assert report["top_genres"] == []
assert report["recommended_styles"] == []
assert isinstance(report["insights"], str)
assert len(report["insights"]) > 0