"""숙박 공통 감성 문구를 한 번 생성한다. 방문 시에는 저장된 문구만 순환한다.""" import asyncio import json import sys from pathlib import Path import httpx sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from services.llm.gemini import DEFAULT_MODEL, call, extract_text PROMPT = """여러 숙박업체 홈페이지 첫 화면에서 돌아가며 보여 줄 한국어 감성 문구 10개를 작성하세요. 호텔, 모텔, 펜션, 게스트하우스 어디에나 쓸 수 있어야 합니다. 휴식, 여행, 머무는 시간, 일상에서의 잠깐의 쉼을 담아 담백하고 따뜻하게 쓰세요. 각 문구는 공백 포함 15~30자. 과장, 진부한 최상급, 상호명, 지명, 계절, 날씨, 바다/숲/정원/독채 등 시설이나 경관, 청결/조식/가격 등 확인이 필요한 사실과 서비스 약속은 금지합니다. 서로 다른 표현으로 정확히 10개, 문자열 JSON 배열만 반환하세요.""" async def main(): async with httpx.AsyncClient(timeout=90) as client: response = await call(client, DEFAULT_MODEL, { "contents": [{"role": "user", "parts": [{"text": PROMPT}]}], "generationConfig": { "responseMimeType": "application/json", "responseSchema": {"type": "ARRAY", "items": {"type": "STRING"}, "minItems": 10, "maxItems": 10}, "temperature": 0.8, }, }, max_retries=0) lines = json.loads(extract_text(response)) if not isinstance(lines, list) or len(lines) != 10 or not all(isinstance(s, str) and 15 <= len(s.strip()) <= 30 for s in lines): raise ValueError("문구 개수·길이 검증 실패") lines = [s.strip() for s in lines] if len(set(lines)) != 10: raise ValueError("중복 문구") target = Path(__file__).resolve().parents[2] / "site/src/lib/lodging-catchphrases.json" target.write_text(json.dumps(lines, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") print(json.dumps({"model": DEFAULT_MODEL, "items": lines}, ensure_ascii=False)) if __name__ == "__main__": asyncio.run(main())