fix(agent-office): YouTubeResearchAgent 품질 개선 (동시실행 가드·에러 로깅·타입 수정)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-01 12:22:33 +09:00
parent 1d4354e402
commit 3b9dcfe0dd
3 changed files with 19 additions and 11 deletions

View File

@@ -1,15 +1,20 @@
# agent-office/app/agents/youtube.py # agent-office/app/agents/youtube.py
import asyncio import asyncio
import logging
from datetime import date from datetime import date
import httpx
from .base import BaseAgent from .base import BaseAgent
from ..db import add_youtube_research_job, update_youtube_research_job from ..db import add_youtube_research_job, update_youtube_research_job, add_log
from ..youtube_researcher import ( from ..youtube_researcher import (
TARGET_COUNTRIES, TREND_KEYWORDS, TARGET_COUNTRIES, TREND_KEYWORDS, MUSIC_LAB_URL,
fetch_youtube_trending, fetch_google_trends, fetch_billboard_top20, fetch_youtube_trending, fetch_google_trends, fetch_billboard_top20,
push_to_music_lab, push_to_music_lab,
) )
logger = logging.getLogger(__name__)
class YouTubeResearchAgent(BaseAgent): class YouTubeResearchAgent(BaseAgent):
agent_id = "youtube" agent_id = "youtube"
@@ -20,6 +25,8 @@ class YouTubeResearchAgent(BaseAgent):
async def on_command(self, command: str, params: dict) -> dict: async def on_command(self, command: str, params: dict) -> dict:
if command == "research": if command == "research":
if self.state == "working":
return {"ok": False, "message": "이미 수집 중"}
countries = params.get("countries", TARGET_COUNTRIES) countries = params.get("countries", TARGET_COUNTRIES)
asyncio.create_task(self._run_research(countries)) asyncio.create_task(self._run_research(countries))
return {"ok": True, "message": f"리서치 시작: {countries}"} return {"ok": True, "message": f"리서치 시작: {countries}"}
@@ -59,15 +66,15 @@ class YouTubeResearchAgent(BaseAgent):
async def send_weekly_report(self) -> None: async def send_weekly_report(self) -> None:
"""매주 월요일 08:00 — 주간 인사이트 텔레그램 발송.""" """매주 월요일 08:00 — 주간 인사이트 텔레그램 발송."""
import httpx
from ..youtube_researcher import MUSIC_LAB_URL
try: try:
async with httpx.AsyncClient(timeout=10.0) as client: async with httpx.AsyncClient(timeout=10.0) as client:
resp = await client.get(f"{MUSIC_LAB_URL}/api/music/market/report/latest") resp = await client.get(f"{MUSIC_LAB_URL}/api/music/market/report/latest")
if resp.status_code != 200: if resp.status_code != 200:
return return
report = resp.json() report = resp.json()
except Exception: except Exception as e:
add_log(self.agent_id, f"주간 리포트 조회 실패: {e}", level="error")
logger.error("send_weekly_report: music-lab 조회 실패: %s", e)
return return
top = report.get("top_genres", [])[:3] top = report.get("top_genres", [])[:3]
@@ -81,5 +88,6 @@ class YouTubeResearchAgent(BaseAgent):
try: try:
from ..telegram_bot import send_message from ..telegram_bot import send_message
await send_message(text) await send_message(text)
except (ImportError, Exception): except (ImportError, Exception) as e:
pass add_log(self.agent_id, f"주간 리포트 텔레그램 발송 실패: {e}", level="error")
logger.error("send_weekly_report: 텔레그램 발송 실패: %s", e)

View File

@@ -542,7 +542,7 @@ def update_youtube_research_job(
def get_latest_youtube_research_job() -> Optional[Dict[str, Any]]: def get_latest_youtube_research_job() -> Optional[Dict[str, Any]]:
with _conn() as conn: with _conn() as conn:
row = conn.execute( row = conn.execute(
"SELECT * FROM youtube_research_jobs ORDER BY started_at DESC LIMIT 1" "SELECT * FROM youtube_research_jobs ORDER BY id DESC LIMIT 1"
).fetchone() ).fetchone()
if not row: if not row:
return None return None

View File

@@ -185,7 +185,7 @@ def activity_feed(limit: int = 50, offset: int = 0):
# --- Realestate Agent Push Endpoint --- # --- Realestate Agent Push Endpoint ---
from pydantic import BaseModel from pydantic import BaseModel
from typing import List, Dict, Any from typing import List, Dict, Any, Optional
class RealestateNotifyBody(BaseModel): class RealestateNotifyBody(BaseModel):
@@ -208,8 +208,8 @@ class YouTubeResearchBody(BaseModel):
@app.post("/api/agent-office/youtube/research") @app.post("/api/agent-office/youtube/research")
async def trigger_youtube_research(body: YouTubeResearchBody = None): async def trigger_youtube_research(body: Optional[YouTubeResearchBody] = None):
agent = AGENT_REGISTRY.get("youtube") agent = get_agent("youtube")
if not agent: if not agent:
raise HTTPException(status_code=503, detail="YouTubeResearchAgent 없음") raise HTTPException(status_code=503, detail="YouTubeResearchAgent 없음")
params = {} params = {}