roadmap 섹션 정보 출력

db-migration
jaehwang 2026-06-02 16:34:18 +09:00
parent 2232273200
commit 45a74ab970
4 changed files with 49 additions and 2 deletions

View File

@ -7,6 +7,7 @@ from integrations.llm.schemas.report import (
YouTubeDiagnosisInput, YouTubeDiagnosisOutput, YouTubeDiagnosisInput, YouTubeDiagnosisOutput,
BrandConsistencyInput, BrandConsistencyOutput, BrandConsistencyInput, BrandConsistencyOutput,
TransformationInput, TransformationProposal, TransformationInput, TransformationProposal,
RoadmapInput, RoadmapOutput,
) )
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 (
@ -114,3 +115,10 @@ transformation_prompt = Prompt(
input_class=TransformationInput, input_class=TransformationInput,
output_class=TransformationProposal, output_class=TransformationProposal,
) )
roadmap_prompt = Prompt(
file_name="roadmap_prompt.txt",
prompt_model="REPORT_MODEL",
input_class=RoadmapInput,
output_class=RoadmapOutput,
)

View File

@ -368,6 +368,17 @@ class CriticalIssuesOutput(BaseModel):
diagnosis: list[DiagnosisItem] diagnosis: list[DiagnosisItem]
# --- Roadmap ---
class RoadmapInput(BaseModel):
clinic_name: str | None = None
data: str | None = None
class RoadmapOutput(BaseModel):
roadmap: list[RoadmapMonth]
# --- Transformation --- # --- Transformation ---
class TransformationInput(BaseModel): class TransformationInput(BaseModel):

View File

@ -0,0 +1,14 @@
다음은 성형외과/피부과 {clinic_name} 의 전 채널 수집 데이터입니다.
{data}
위 데이터를 바탕으로 이 병원의 3개월 마케팅 실행 로드맵을 수립해줘.
month 1, 2, 3 각각 하나씩, 총 3개 항목을 포함한 roadmap JSON 배열로 출력해줘.
각 항목은 아래 형식을 따라줘:
- month: 월 번호 (1, 2, 3)
- title: 해당 월의 핵심 테마 (예: "브랜드 정비")
- subtitle: 한 줄 부제 (예: "기반 구축 — 로고·계정 통일")
- tasks: 실행 과제 목록, 각 과제는 task(string)와 completed(false)로 구성
출처 번호([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, critical_issues_prompt, transformation_prompt from integrations.llm.prompt import report_prompt, plan_prompt, youtube_diagnosis_prompt, brand_consistency_prompt, critical_issues_prompt, transformation_prompt, roadmap_prompt
from integrations.llm.schemas.report import ReportOutput, ClinicSnapshot, YouTubeAudit, BrandConsistencyOutput, CriticalIssuesOutput, DiagnosisItem, TransformationProposal from integrations.llm.schemas.report import ReportOutput, ClinicSnapshot, YouTubeAudit, BrandConsistencyOutput, CriticalIssuesOutput, DiagnosisItem, TransformationProposal, RoadmapOutput, RoadmapMonth
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_roadmap(analysis_run_id: str, raw: dict) -> list[dict]:
result: RoadmapOutput = await LLMService(provider="perplexity").generate(
roadmap_prompt,
{
"clinic_name": (raw.get("mainpage") or {}).get("clinicName"),
"data": json.dumps(raw, ensure_ascii=False),
},
)
return [RoadmapMonth.model_validate(item).model_dump() for item in result.roadmap]
async def _build_transformation(analysis_run_id: str, raw: dict) -> dict: async def _build_transformation(analysis_run_id: str, raw: dict) -> dict:
result: TransformationProposal = await LLMService(provider="perplexity").generate( result: TransformationProposal = await LLMService(provider="perplexity").generate(
transformation_prompt, transformation_prompt,
@ -267,6 +278,7 @@ async def _build_overrides(analysis_run_id: str) -> dict:
brand_patch = brand.model_dump()["brand_inconsistencies"] brand_patch = brand.model_dump()["brand_inconsistencies"]
critical_issues = await _build_critical_issues(analysis_run_id, raw) critical_issues = await _build_critical_issues(analysis_run_id, raw)
transformation = await _build_transformation(analysis_run_id, raw) transformation = await _build_transformation(analysis_run_id, raw)
roadmap = await _build_roadmap(analysis_run_id, raw)
fb_patch: dict = {} fb_patch: dict = {}
if fb_pages: if fb_pages:
@ -287,6 +299,8 @@ async def _build_overrides(analysis_run_id: str) -> dict:
overrides["problem_diagnosis"] = critical_issues overrides["problem_diagnosis"] = critical_issues
if transformation: if transformation:
overrides["transformation"] = transformation overrides["transformation"] = transformation
if roadmap:
overrides["roadmap"] = roadmap
return overrides return overrides