Files
moreminimore-marketing/backend/api/podcast/handlers/research.py
Kunthawat Greethong c35fa52117 Base code
2026-01-08 22:39:53 +07:00

100 lines
3.5 KiB
Python

"""
Podcast Research Handlers
Research endpoints using Exa provider.
"""
from fastapi import APIRouter, Depends, HTTPException
from typing import Dict, Any
from types import SimpleNamespace
from middleware.auth_middleware import get_current_user
from api.story_writer.utils.auth import require_authenticated_user
from services.blog_writer.research.exa_provider import ExaResearchProvider
from loguru import logger
from ..models import (
PodcastExaResearchRequest,
PodcastExaResearchResponse,
PodcastExaSource,
PodcastExaConfig,
)
router = APIRouter()
@router.post("/research/exa", response_model=PodcastExaResearchResponse)
async def podcast_research_exa(
request: PodcastExaResearchRequest,
current_user: Dict[str, Any] = Depends(get_current_user),
):
"""
Run podcast research directly via Exa (no blog writer pipeline).
"""
user_id = require_authenticated_user(current_user)
queries = [q.strip() for q in request.queries if q and q.strip()]
if not queries:
raise HTTPException(status_code=400, detail="At least one query is required for research.")
exa_cfg = request.exa_config or PodcastExaConfig()
cfg = SimpleNamespace(
exa_search_type=exa_cfg.exa_search_type or "auto",
exa_category=exa_cfg.exa_category,
exa_include_domains=exa_cfg.exa_include_domains or [],
exa_exclude_domains=exa_cfg.exa_exclude_domains or [],
max_sources=exa_cfg.max_sources or 8,
source_types=[],
)
provider = ExaResearchProvider()
prompt = request.topic
try:
result = await provider.search(
prompt=prompt,
topic=request.topic,
industry="",
target_audience="",
config=cfg,
user_id=user_id,
)
except Exception as exc:
logger.error(f"[Podcast Exa Research] Failed for user {user_id}: {exc}")
raise HTTPException(status_code=500, detail=f"Exa research failed: {exc}")
# Track usage if available
try:
cost_total = 0.0
if isinstance(result, dict):
cost_total = result.get("cost", {}).get("total", 0.005) if result.get("cost") else 0.005
provider.track_exa_usage(user_id, cost_total)
except Exception as track_err:
logger.warning(f"[Podcast Exa Research] Failed to track usage: {track_err}")
sources_payload = []
if isinstance(result, dict):
for src in result.get("sources", []) or []:
try:
sources_payload.append(PodcastExaSource(**src))
except Exception:
sources_payload.append(PodcastExaSource(**{
"title": src.get("title", ""),
"url": src.get("url", ""),
"excerpt": src.get("excerpt", ""),
"published_at": src.get("published_at"),
"highlights": src.get("highlights"),
"summary": src.get("summary"),
"source_type": src.get("source_type"),
"index": src.get("index"),
}))
return PodcastExaResearchResponse(
sources=sources_payload,
search_queries=result.get("search_queries", queries) if isinstance(result, dict) else queries,
cost=result.get("cost") if isinstance(result, dict) else None,
search_type=result.get("search_type") if isinstance(result, dict) else None,
provider=result.get("provider", "exa") if isinstance(result, dict) else "exa",
content=result.get("content") if isinstance(result, dict) else None,
)