o2o-infinith-backend/app/services/market.py

65 lines
2.4 KiB
Python

import asyncio
import logging
from common.db.run import select_run
from common.db.hospital import select_hospital
from common.db.market import upsert_market_status, upsert_market_result
from common.db.source import select_run_raw_data
from integrations.llm.llm_service import LLMService
from integrations.llm.prompt import (
market_competitors_prompt,
market_keywords_prompt,
market_trend_prompt,
market_target_audience_prompt,
)
logger = logging.getLogger(__name__)
_TYPES = ["competitors", "keywords", "trend", "target_audience"]
async def _save(analysis_run_id: str, analysis_type: str, result, exc: Exception | None) -> None:
if exc:
logger.warning("[market] %s failed run=%s: %s", analysis_type, analysis_run_id, exc)
await upsert_market_status(analysis_run_id, analysis_type, "failed")
else:
await upsert_market_result(analysis_run_id, analysis_type, result.model_dump())
async def run_market_analysis(analysis_run_id: str) -> None:
logger.info("[market] start run=%s", analysis_run_id)
run = await select_run(analysis_run_id)
clinic = await select_hospital(run["hospital_id"])
raw = await select_run_raw_data(analysis_run_id)
mainpage = raw.get("mainpage") or {}
clinic_name = (clinic or {}).get("hospital_name") or ""
address = (clinic or {}).get("road_address") or ""
services = mainpage.get("services", [])
services_str = ", ".join(services[:3])
primary_service = services[0] if services else ""
for analysis_type in _TYPES:
await upsert_market_status(analysis_run_id, analysis_type, "processing")
llm = LLMService(provider="perplexity")
results = await asyncio.gather(
llm.generate(market_competitors_prompt, {"address": address, "services": services_str}),
llm.generate(market_keywords_prompt, {"services": services_str}),
llm.generate(market_trend_prompt, {"service": primary_service}),
llm.generate(market_target_audience_prompt, {"clinic_name": clinic_name}),
return_exceptions=True,
)
# 그다지 좋은 방식은 아님
await asyncio.gather(*[
_save(
analysis_run_id,
analysis_type,
result=None if isinstance(r, Exception) else r,
exc=r if isinstance(r, Exception) else None,
)
for analysis_type, r in zip(_TYPES, results)
])
logger.info("[market] done run=%s", analysis_run_id)