critical_issues 섹션 정보 출력

db-migration
jaehwang 2026-06-02 15:31:06 +09:00
parent 35e5e98524
commit 484ee41810
4 changed files with 53 additions and 3 deletions

View File

@ -1,7 +1,12 @@
import os import os
from pydantic import BaseModel from pydantic import BaseModel
from common.utils import get_env from common.utils import get_env
from integrations.llm.schemas.report import ReportInput, ReportOutput, YouTubeDiagnosisInput, YouTubeDiagnosisOutput, BrandConsistencyInput, BrandConsistencyOutput from integrations.llm.schemas.report import (
ReportInput, ReportOutput,
CriticalIssuesInput, CriticalIssuesOutput,
YouTubeDiagnosisInput, YouTubeDiagnosisOutput,
BrandConsistencyInput, BrandConsistencyOutput,
)
from integrations.llm.schemas.plan import PlanInput, PlanOutput from integrations.llm.schemas.plan import PlanInput, PlanOutput
from integrations.llm.schemas.market import ( from integrations.llm.schemas.market import (
MarketCompetitorsInput, MarketCompetitorsOutput, MarketCompetitorsInput, MarketCompetitorsOutput,
@ -94,3 +99,10 @@ brand_consistency_prompt = Prompt(
input_class=BrandConsistencyInput, input_class=BrandConsistencyInput,
output_class=BrandConsistencyOutput, output_class=BrandConsistencyOutput,
) )
critical_issues_prompt = Prompt(
file_name="critical_issues_prompt.txt",
prompt_model="REPORT_MODEL",
input_class=CriticalIssuesInput,
output_class=CriticalIssuesOutput,
)

View File

@ -357,6 +357,17 @@ class YouTubeDiagnosisOutput(BaseModel):
diagnosis: list[DiagnosisItem] diagnosis: list[DiagnosisItem]
# --- Diagnosis ---
class CriticalIssuesInput(BaseModel):
clinic_name: str | None = None
data: str | None = None
class CriticalIssuesOutput(BaseModel):
diagnosis: list[DiagnosisItem]
# --- BrandConsistency --- # --- BrandConsistency ---
class BrandConsistencyInput(BaseModel): class BrandConsistencyInput(BaseModel):

View File

@ -0,0 +1,13 @@
다음은 성형외과/피부과 {clinic_name} 의 전 채널 수집 데이터입니다.
{data}
위 데이터를 바탕으로 이 병원의 마케팅 전반에 걸친 핵심 문제점과 개선사항을 진단해줘.
각 항목은 category(진단 카테고리), detail(상세 설명), severity(critical/warning/info) 형식의 JSON 배열로 출력해줘.
현재 주요 진단 카테고리는 3개야.
브랜드 아이덴티티 파편화
콘텐츠 전략 부재
플랫폼 간 유입 단절
출처 번호([1], [2] 등)는 포함하지 마.

View File

@ -8,8 +8,8 @@ from common.db.run import select_run, update_run_report, update_run_plan
from common.db.source import select_run_raw_data, select_run_mainpage_url from common.db.source import select_run_raw_data, select_run_mainpage_url
from common.db.market import select_market from common.db.market import select_market
from integrations.llm.llm_service import LLMService from integrations.llm.llm_service import LLMService
from integrations.llm.prompt import report_prompt, plan_prompt, youtube_diagnosis_prompt, brand_consistency_prompt from integrations.llm.prompt import report_prompt, plan_prompt, youtube_diagnosis_prompt, brand_consistency_prompt, critical_issues_prompt
from integrations.llm.schemas.report import ReportOutput, ClinicSnapshot, YouTubeAudit, BrandConsistencyOutput from integrations.llm.schemas.report import ReportOutput, ClinicSnapshot, YouTubeAudit, BrandConsistencyOutput, CriticalIssuesOutput, DiagnosisItem
from integrations.llm.schemas.plan import PlanOutput from integrations.llm.schemas.plan import PlanOutput
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -208,6 +208,17 @@ async def _build_youtube_audit(youtube: dict) -> dict:
return YouTubeAudit.model_validate(yt_patch).model_dump() return YouTubeAudit.model_validate(yt_patch).model_dump()
async def _build_critical_issues(analysis_run_id: str, raw: dict) -> list[dict]:
result: CriticalIssuesOutput = await LLMService(provider="perplexity").generate(
critical_issues_prompt,
{
"clinic_name": (raw.get("mainpage") or {}).get("clinicName"),
"data": json.dumps(raw, ensure_ascii=False),
},
)
return [DiagnosisItem.model_validate(item).model_dump() for item in result.diagnosis]
async def _build_overrides(analysis_run_id: str) -> dict: async def _build_overrides(analysis_run_id: str) -> dict:
raw = await select_run_raw_data(analysis_run_id) raw = await select_run_raw_data(analysis_run_id)
if not raw: if not raw:
@ -243,6 +254,7 @@ async def _build_overrides(analysis_run_id: str) -> dict:
brand = await generate_brand_consistency(analysis_run_id) brand = await generate_brand_consistency(analysis_run_id)
brand_patch = brand.model_dump()["brand_inconsistencies"] brand_patch = brand.model_dump()["brand_inconsistencies"]
critical_issues = await _build_critical_issues(analysis_run_id, raw)
fb_patch: dict = {} fb_patch: dict = {}
if fb_pages: if fb_pages:
@ -259,6 +271,8 @@ async def _build_overrides(analysis_run_id: str) -> dict:
overrides["facebook_audit"] = fb_patch overrides["facebook_audit"] = fb_patch
if yt_patch: if yt_patch:
overrides["youtube_audit"] = yt_patch overrides["youtube_audit"] = yt_patch
if critical_issues:
overrides["problem_diagnosis"] = critical_issues
return overrides return overrides