From 223227320008857beed7fd5c63dda25af7169be4 Mon Sep 17 00:00:00 2001 From: jaehwang Date: Tue, 2 Jun 2026 16:21:19 +0900 Subject: [PATCH] =?UTF-8?q?transformation=20=EC=84=B9=EC=85=98=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=B6=9C=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/integrations/llm/prompt.py | 8 ++++++++ app/integrations/llm/schemas/report.py | 7 +++++++ .../llm/temp-prompt/transformation_prompt.txt | 14 ++++++++++++++ app/services/analysis.py | 18 ++++++++++++++++-- 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 app/integrations/llm/temp-prompt/transformation_prompt.txt diff --git a/app/integrations/llm/prompt.py b/app/integrations/llm/prompt.py index 3ee76d4..4d6a06b 100644 --- a/app/integrations/llm/prompt.py +++ b/app/integrations/llm/prompt.py @@ -6,6 +6,7 @@ from integrations.llm.schemas.report import ( CriticalIssuesInput, CriticalIssuesOutput, YouTubeDiagnosisInput, YouTubeDiagnosisOutput, BrandConsistencyInput, BrandConsistencyOutput, + TransformationInput, TransformationProposal, ) from integrations.llm.schemas.plan import PlanInput, PlanOutput from integrations.llm.schemas.market import ( @@ -106,3 +107,10 @@ critical_issues_prompt = Prompt( input_class=CriticalIssuesInput, output_class=CriticalIssuesOutput, ) + +transformation_prompt = Prompt( + file_name="transformation_prompt.txt", + prompt_model="REPORT_MODEL", + input_class=TransformationInput, + output_class=TransformationProposal, +) diff --git a/app/integrations/llm/schemas/report.py b/app/integrations/llm/schemas/report.py index 8bbee91..f9dc896 100644 --- a/app/integrations/llm/schemas/report.py +++ b/app/integrations/llm/schemas/report.py @@ -368,6 +368,13 @@ class CriticalIssuesOutput(BaseModel): diagnosis: list[DiagnosisItem] +# --- Transformation --- + +class TransformationInput(BaseModel): + clinic_name: str | None = None + data: str | None = None + + # --- BrandConsistency --- class BrandConsistencyInput(BaseModel): diff --git a/app/integrations/llm/temp-prompt/transformation_prompt.txt b/app/integrations/llm/temp-prompt/transformation_prompt.txt new file mode 100644 index 0000000..58beb39 --- /dev/null +++ b/app/integrations/llm/temp-prompt/transformation_prompt.txt @@ -0,0 +1,14 @@ +다음은 성형외과/피부과 {clinic_name} 의 전 채널 수집 데이터입니다. + +{data} + +위 데이터를 바탕으로 이 병원의 마케팅 전환 전략을 수립해줘. +아래 5개 항목을 포함한 JSON을 출력해줘. + +1. brand_identity: 브랜드 아이덴티티 개선 항목 (area, as_is, to_be) +2. content_strategy: 콘텐츠 전략 개선 항목 (area, as_is, to_be) +3. platform_strategies: 플랫폼별 전략 (platform, icon, current_metric, target_metric, strategies[{strategy, detail}]) +4. website_improvements: 웹사이트 개선 항목 (area, as_is, to_be) +5. new_channel_proposals: 신규 채널 제안 (channel, priority, rationale) + +출처 번호([1], [2] 등)는 포함하지 마. diff --git a/app/services/analysis.py b/app/services/analysis.py index 48dcea9..b6d67cc 100644 --- a/app/services/analysis.py +++ b/app/services/analysis.py @@ -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.market import select_market from integrations.llm.llm_service import LLMService -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, CriticalIssuesOutput, DiagnosisItem +from integrations.llm.prompt import report_prompt, plan_prompt, youtube_diagnosis_prompt, brand_consistency_prompt, critical_issues_prompt, transformation_prompt +from integrations.llm.schemas.report import ReportOutput, ClinicSnapshot, YouTubeAudit, BrandConsistencyOutput, CriticalIssuesOutput, DiagnosisItem, TransformationProposal from integrations.llm.schemas.plan import PlanOutput logger = logging.getLogger(__name__) @@ -208,6 +208,17 @@ async def _build_youtube_audit(youtube: dict) -> dict: return YouTubeAudit.model_validate(yt_patch).model_dump() +async def _build_transformation(analysis_run_id: str, raw: dict) -> dict: + result: TransformationProposal = await LLMService(provider="perplexity").generate( + transformation_prompt, + { + "clinic_name": (raw.get("mainpage") or {}).get("clinicName"), + "data": json.dumps(raw, ensure_ascii=False), + }, + ) + return result.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, @@ -255,6 +266,7 @@ async def _build_overrides(analysis_run_id: str) -> dict: brand = await generate_brand_consistency(analysis_run_id) brand_patch = brand.model_dump()["brand_inconsistencies"] critical_issues = await _build_critical_issues(analysis_run_id, raw) + transformation = await _build_transformation(analysis_run_id, raw) fb_patch: dict = {} if fb_pages: @@ -273,6 +285,8 @@ async def _build_overrides(analysis_run_id: str) -> dict: overrides["youtube_audit"] = yt_patch if critical_issues: overrides["problem_diagnosis"] = critical_issues + if transformation: + overrides["transformation"] = transformation return overrides