fix(music-lab): market API 타입 강화·ANTHROPIC_API_KEY call-time·HTTP 레이어 테스트 추가
This commit is contained in:
@@ -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)}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user