마켓 분석 데이터 추가

upload
jaehwang 2026-05-19 15:45:44 +09:00
parent cda518c027
commit 20fdf53264
6 changed files with 91 additions and 17 deletions

View File

@ -59,6 +59,17 @@ async def fetchone(sql: str, args: tuple = ()) -> dict | None:
finally: finally:
conn.close() conn.close()
async def fetchall(sql: str, args: tuple = ()) -> list[dict]:
pool = await get_pool()
async with pool.acquire() as conn:
try:
async with conn.cursor(aiomysql.DictCursor) as cur:
await cur.execute(sql, args)
return await cur.fetchall()
finally:
conn.close()
async def insert_instagram_row(hospital_id: str, url: str) -> int: async def insert_instagram_row(hospital_id: str, url: str) -> int:
return await execute("INSERT INTO instagram_data (hospital_id, url) VALUES (%s, %s)", (hospital_id, url)) return await execute("INSERT INTO instagram_data (hospital_id, url) VALUES (%s, %s)", (hospital_id, url))
@ -247,3 +258,14 @@ async def save_hospital_raw_data(hospital_id: str, data: dict, analysis_run_id:
), ),
) )
await _insert_hospital_history(hospital_id, analysis_run_id) await _insert_hospital_history(hospital_id, analysis_run_id)
async def get_market_analysis(analysis_run_id: str) -> dict:
rows = await fetchall(
"SELECT analysis_type, data FROM market_analysis WHERE analysis_run_id = %s AND status = 'done'",
(analysis_run_id,),
)
return {
row["analysis_type"]: json.loads(row["data"]) if isinstance(row["data"], str) else row["data"]
for row in rows
}

View File

@ -11,6 +11,10 @@ class PlanInput(BaseModel):
services: str | None = None services: str | None = None
doctors: str | None = None doctors: str | None = None
report: str | None = None report: str | None = None
market_competitors: str | None = None
market_keywords: str | None = None
market_trend: str | None = None
market_target_audience: str | None = None
# --- BrandGuide --- # --- BrandGuide ---

View File

@ -317,6 +317,10 @@ class ReportInput(BaseModel):
naver_blog: str | None = None naver_blog: str | None = None
youtube: str | None = None youtube: str | None = None
gangnam_unni: str | None = None gangnam_unni: str | None = None
market_competitors: str | None = None
market_keywords: str | None = None
market_trend: str | None = None
market_target_audience: str | None = None
# --- MarketingReport --- # --- MarketingReport ---

View File

@ -15,6 +15,20 @@
- 시술: {services} - 시술: {services}
- 의료진: {doctors} - 의료진: {doctors}
## 시장 분석 데이터
### 경쟁 병원
{market_competitors}
### 검색 키워드 트렌드
{market_keywords}
### 시장 트렌드
{market_trend}
### 잠재 고객 분석
{market_target_audience}
## 분석 리포트 ## 분석 리포트
{report} {report}

View File

@ -12,6 +12,20 @@
- 시술: {services} - 시술: {services}
- 의료진: {doctors} - 의료진: {doctors}
## 시장 분석 데이터
### 경쟁 병원
{market_competitors}
### 검색 키워드 트렌드
{market_keywords}
### 시장 트렌드
{market_trend}
### 잠재 고객 분석
{market_target_audience}
## 채널 데이터 ## 채널 데이터
### 인스타그램 ### 인스타그램

View File

@ -1,6 +1,6 @@
import json import json
import logging import logging
from common.db import fetchone, execute, get_analysis_raw_data, save_analysis_report from common.db import fetchone, execute, get_analysis_raw_data, save_analysis_report, get_market_analysis
from integrations.llm.llm_service import LLMService from integrations.llm.llm_service import LLMService
from integrations.llm.prompt import report_prompt, plan_prompt from integrations.llm.prompt import report_prompt, plan_prompt
from integrations.llm.schemas.report import ReportOutput from integrations.llm.schemas.report import ReportOutput
@ -22,6 +22,10 @@ async def generate_report(analysis_run_id: str) -> ReportOutput:
raw_data = clinic_row["raw_data"] if clinic_row else None raw_data = clinic_row["raw_data"] if clinic_row else None
clinic = json.loads(raw_data) if isinstance(raw_data, str) else (raw_data or {}) clinic = json.loads(raw_data) if isinstance(raw_data, str) else (raw_data or {})
raw = await get_analysis_raw_data(analysis_run_id) raw = await get_analysis_raw_data(analysis_run_id)
market = await get_market_analysis(analysis_run_id)
def _json(v) -> str | None:
return json.dumps(v, ensure_ascii=False) if v else None
input_data = { input_data = {
"clinic_name": clinic.get("clinicName"), "clinic_name": clinic.get("clinicName"),
@ -31,8 +35,12 @@ async def generate_report(analysis_run_id: str) -> ReportOutput:
"slogan": clinic.get("slogan"), "slogan": clinic.get("slogan"),
"services": json.dumps(clinic.get("services", []), ensure_ascii=False), "services": json.dumps(clinic.get("services", []), ensure_ascii=False),
"doctors": json.dumps(clinic.get("doctors", []), ensure_ascii=False), "doctors": json.dumps(clinic.get("doctors", []), ensure_ascii=False),
"market_competitors": _json(market.get("competitors")),
"market_keywords": _json(market.get("keywords")),
"market_trend": _json(market.get("trend")),
"market_target_audience": _json(market.get("target_audience")),
**{ **{
channel: json.dumps(data, ensure_ascii=False) if data else None channel: _json(data)
for channel, data in raw.items() for channel, data in raw.items()
}, },
} }
@ -53,6 +61,10 @@ async def generate_plan(analysis_run_id: str) -> PlanOutput:
clinic = json.loads(raw_data) if isinstance(raw_data, str) else (raw_data or {}) clinic = json.loads(raw_data) if isinstance(raw_data, str) else (raw_data or {})
report_data = run["report_data"] report_data = run["report_data"]
report = json.loads(report_data) if isinstance(report_data, str) else report_data report = json.loads(report_data) if isinstance(report_data, str) else report_data
market = await get_market_analysis(analysis_run_id)
def _json(v) -> str | None:
return json.dumps(v, ensure_ascii=False) if v else None
input_data = { input_data = {
"clinic_name": clinic.get("clinicName"), "clinic_name": clinic.get("clinicName"),
@ -62,7 +74,11 @@ async def generate_plan(analysis_run_id: str) -> PlanOutput:
"slogan": clinic.get("slogan"), "slogan": clinic.get("slogan"),
"services": json.dumps(clinic.get("services", []), ensure_ascii=False), "services": json.dumps(clinic.get("services", []), ensure_ascii=False),
"doctors": json.dumps(clinic.get("doctors", []), ensure_ascii=False), "doctors": json.dumps(clinic.get("doctors", []), ensure_ascii=False),
"report": json.dumps(report, ensure_ascii=False) if report else None, "report": _json(report),
"market_competitors": _json(market.get("competitors")),
"market_keywords": _json(market.get("keywords")),
"market_trend": _json(market.get("trend")),
"market_target_audience": _json(market.get("target_audience")),
} }
return await LLMService(provider="perplexity").generate(plan_prompt, input_data) return await LLMService(provider="perplexity").generate(plan_prompt, input_data)