report 패치 함수 추가. 데이터 직결용

insta-data
jaehwang 2026-05-20 17:16:19 +09:00
parent 1f45b3e53d
commit 09bb7a71ee
2 changed files with 82 additions and 8 deletions

View File

@ -148,7 +148,7 @@ async def is_done(table: str, row_id: int | None) -> bool:
return r["status"] == "done"
async def _fetch_raw(table: str, row_id: int | None) -> dict | None:
async def fetch_raw(table: str, row_id: int | None) -> dict | None:
if row_id is None:
return None
row = await fetchone(f"SELECT raw_data FROM {table} WHERE id = %s", (row_id,))
@ -164,11 +164,11 @@ async def get_analysis_raw_data(analysis_run_id: str) -> dict:
(analysis_run_id,),
)
return {
"instagram": await _fetch_raw("instagram_data", run["instagram_data_id"]),
"facebook": await _fetch_raw("facebook_data", run["facebook_data_id"]),
"naver_blog": await _fetch_raw("naver_blog_data", run["naver_blog_data_id"]),
"youtube": await _fetch_raw("youtube_data", run["youtube_data_id"]),
"gangnam_unni": await _fetch_raw("gangnam_unni_data", run["gangnam_unni_data_id"]),
"instagram": await fetch_raw("instagram_data", run["instagram_data_id"]),
"facebook": await fetch_raw("facebook_data", run["facebook_data_id"]),
"naver_blog": await fetch_raw("naver_blog_data", run["naver_blog_data_id"]),
"youtube": await fetch_raw("youtube_data", run["youtube_data_id"]),
"gangnam_unni": await fetch_raw("gangnam_unni_data", run["gangnam_unni_data_id"]),
}

View File

@ -1,6 +1,6 @@
import json
import logging
from common.db import fetchone, execute, get_analysis_raw_data, save_analysis_report, get_market_analysis
from common.db import fetchone, execute, fetch_raw, get_analysis_raw_data, save_analysis_report, get_market_analysis
from integrations.llm.llm_service import LLMService
from integrations.llm.prompt import report_prompt, plan_prompt
from integrations.llm.schemas.report import ReportOutput
@ -47,7 +47,6 @@ async def generate_report(analysis_run_id: str) -> ReportOutput:
return await LLMService(provider="perplexity").generate(report_prompt, input_data)
async def generate_plan(analysis_run_id: str) -> PlanOutput:
run = await fetchone(
"SELECT hospital_id, report_data FROM analysis_runs WHERE analysis_run_id = %s",
@ -84,9 +83,84 @@ async def generate_plan(analysis_run_id: str) -> PlanOutput:
return await LLMService(provider="perplexity").generate(plan_prompt, input_data)
async def _build_overrides(analysis_run_id: str) -> dict:
run = await fetchone(
"SELECT hospital_id, instagram_data_id, facebook_data_id,"
" naver_blog_data_id, youtube_data_id, gangnam_unni_data_id"
" FROM analysis_runs WHERE analysis_run_id = %s",
(analysis_run_id,),
)
if not run:
return {}
hospital_row = await fetchone(
"SELECT raw_data FROM hospital_baseinfo WHERE hospital_id = %s",
(run["hospital_id"],),
)
hospital = json.loads(hospital_row["raw_data"]) if hospital_row and isinstance(hospital_row.get("raw_data"), str) else (hospital_row or {}).get("raw_data") or {}
instagram = await fetch_raw("instagram_data", run["instagram_data_id"]) or {}
facebook = await fetch_raw("facebook_data", run["facebook_data_id"]) or {}
naver_blog = await fetch_raw("naver_blog_data", run["naver_blog_data_id"]) or {}
youtube = await fetch_raw("youtube_data", run["youtube_data_id"]) or {}
gangnam_unni = await fetch_raw("gangnam_unni_data", run["gangnam_unni_data_id"]) or {}
snapshot: dict = {}
# ── gangnam_unni ──────────────────────────────────────────────────────────
doctors = gangnam_unni.get("doctors", [])
lead = max(doctors, key=lambda d: d.get("reviews", 0)) if doctors else None
if gangnam_unni.get("name"): snapshot["name"] = gangnam_unni["name"]
if gangnam_unni.get("rating"): snapshot["overall_rating"] = gangnam_unni["rating"]
if gangnam_unni.get("totalReviews"): snapshot["total_reviews"] = gangnam_unni["totalReviews"]
if gangnam_unni.get("address"): snapshot["location"] = gangnam_unni["address"]
if gangnam_unni.get("badges"): snapshot["certifications"] = gangnam_unni["badges"]
if doctors: snapshot["staff_count"] = len(doctors)
if lead:
snapshot["lead_doctor"] = {
"name": lead.get("name"),
"credentials": lead.get("specialty"),
"rating": lead.get("rating"),
"review_count": lead.get("reviews"),
}
# ── instagram ─────────────────────────────────────────────────────────────
ig_patch: dict = {}
if instagram.get("username"): ig_patch["handle"] = instagram["username"]
if instagram.get("posts"): ig_patch["posts"] = instagram["posts"]
if instagram.get("followers"): ig_patch["followers"] = instagram["followers"]
if instagram.get("following"): ig_patch["following"] = instagram["following"]
if instagram.get("bio"): ig_patch["bio"] = instagram["bio"]
if instagram.get("username"): ig_patch["profile_link"] = f"https://www.instagram.com/{instagram['username']}/"
overrides: dict = {}
if snapshot:
overrides["clinic_snapshot"] = snapshot
if ig_patch:
overrides["instagram_audit"] = {"accounts": [ig_patch]}
return overrides
def _deep_merge(base: dict, overrides: dict) -> dict:
for k, v in overrides.items():
if isinstance(v, dict) and isinstance(base.get(k), dict):
_deep_merge(base[k], v)
elif isinstance(v, list) and isinstance(base.get(k), list):
for i, item in enumerate(v):
if i < len(base[k]) and isinstance(item, dict) and isinstance(base[k][i], dict):
_deep_merge(base[k][i], item)
else:
base[k] = v
return base
def _patch_report(result: ReportOutput, overrides: dict) -> ReportOutput:
merged = _deep_merge(result.model_dump(), overrides)
return ReportOutput(**merged)
async def run_report_task(analysis_run_id: str) -> None:
logger.info("[report] start run=%s", analysis_run_id)
result = await generate_report(analysis_run_id)
result = _patch_report(result, await _build_overrides(analysis_run_id))
await save_analysis_report(analysis_run_id, result.model_dump())
logger.info("[report] done run=%s", analysis_run_id)