마켓 분석 데이터 추가
parent
cda518c027
commit
20fdf53264
|
|
@ -59,6 +59,17 @@ async def fetchone(sql: str, args: tuple = ()) -> dict | None:
|
|||
finally:
|
||||
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:
|
||||
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)
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ class PlanInput(BaseModel):
|
|||
services: str | None = None
|
||||
doctors: 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 ---
|
||||
|
|
|
|||
|
|
@ -317,6 +317,10 @@ class ReportInput(BaseModel):
|
|||
naver_blog: str | None = None
|
||||
youtube: 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 ---
|
||||
|
|
|
|||
|
|
@ -15,6 +15,20 @@
|
|||
- 시술: {services}
|
||||
- 의료진: {doctors}
|
||||
|
||||
## 시장 분석 데이터
|
||||
|
||||
### 경쟁 병원
|
||||
{market_competitors}
|
||||
|
||||
### 검색 키워드 트렌드
|
||||
{market_keywords}
|
||||
|
||||
### 시장 트렌드
|
||||
{market_trend}
|
||||
|
||||
### 잠재 고객 분석
|
||||
{market_target_audience}
|
||||
|
||||
## 분석 리포트
|
||||
{report}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,20 @@
|
|||
- 시술: {services}
|
||||
- 의료진: {doctors}
|
||||
|
||||
## 시장 분석 데이터
|
||||
|
||||
### 경쟁 병원
|
||||
{market_competitors}
|
||||
|
||||
### 검색 키워드 트렌드
|
||||
{market_keywords}
|
||||
|
||||
### 시장 트렌드
|
||||
{market_trend}
|
||||
|
||||
### 잠재 고객 분석
|
||||
{market_target_audience}
|
||||
|
||||
## 채널 데이터
|
||||
|
||||
### 인스타그램
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
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.prompt import report_prompt, plan_prompt
|
||||
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
|
||||
clinic = json.loads(raw_data) if isinstance(raw_data, str) else (raw_data or {})
|
||||
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 = {
|
||||
"clinic_name": clinic.get("clinicName"),
|
||||
|
|
@ -31,8 +35,12 @@ async def generate_report(analysis_run_id: str) -> ReportOutput:
|
|||
"slogan": clinic.get("slogan"),
|
||||
"services": json.dumps(clinic.get("services", []), 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()
|
||||
},
|
||||
}
|
||||
|
|
@ -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 {})
|
||||
report_data = run["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 = {
|
||||
"clinic_name": clinic.get("clinicName"),
|
||||
|
|
@ -62,7 +74,11 @@ async def generate_plan(analysis_run_id: str) -> PlanOutput:
|
|||
"slogan": clinic.get("slogan"),
|
||||
"services": json.dumps(clinic.get("services", []), 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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue