{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "e7af5103-62db-4a32-b431-6395c85d7ac9", "metadata": {}, "outputs": [], "source": [ "from app.home.api.routers.v1.home import crawling\n", "from app.utils.prompts import prompts" ] }, { "cell_type": "code", "execution_count": 2, "id": "6cf7ae9b-3ffe-4046-9cab-f33bc071b288", "metadata": {}, "outputs": [], "source": [ "from config import crawler_settings" ] }, { "cell_type": "code", "execution_count": 3, "id": "4c4ec4c5-9efb-470f-99cf-a18a5b80352f", "metadata": {}, "outputs": [], "source": [ "from app.home.schemas.home_schema import (\n", " CrawlingRequest,\n", " CrawlingResponse,\n", " ErrorResponse,\n", " ImageUploadResponse,\n", " ImageUploadResultItem,\n", " ImageUrlItem,\n", " MarketingAnalysis,\n", " ProcessedInfo,\n", ")\n", "import json" ] }, { "cell_type": "code", "execution_count": 4, "id": "be5d0e16-8cc6-44d4-ae93-8252caa09940", "metadata": {}, "outputs": [], "source": [ "val1 = CrawlingRequest(**{\"url\" : 'https://map.naver.com/p/entry/place/1903455560?placePath=/home?from=map&fromPanelNum=1&additionalHeight=76×tamp=202601131552&locale=ko&svcName=map_pcv5&businessCategory=pension&c=15.00,0,0,0,dh'})" ] }, { "cell_type": "code", "execution_count": 5, "id": "c13742d7-70f4-4a6d-90c2-8b84f245a08c", "metadata": {}, "outputs": [], "source": [ "from app.utils.prompts.prompts import reload_all_prompt\n", "reload_all_prompt()" ] }, { "cell_type": "code", "execution_count": 6, "id": "d4db2ec1-b2af-4993-8832-47f380c17015", "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2026-01-19 14:13:53] [INFO] [home:crawling:110] [crawling] ========== START ==========\n", "[2026-01-19 14:13:53] [INFO] [home:crawling:111] [crawling] URL: https://map.naver.com/p/entry/place/1903455560?placePath=/home?from=map&fromPane...\n", "[2026-01-19 14:13:53] [INFO] [home:crawling:115] [crawling] Step 1: 네이버 지도 크롤링 시작...\n", "[2026-01-19 14:13:53] [INFO] [scraper:_call_get_accommodation:140] [NvMapScraper] Requesting place_id: 1903455560\n", "[2026-01-19 14:13:53] [INFO] [scraper:_call_get_accommodation:149] [NvMapScraper] SUCCESS - place_id: 1903455560\n", "[2026-01-19 14:13:51] [INFO] [home:crawling:138] [crawling] Step 1 완료 - 이미지 44개 (735.1ms)\n", "[2026-01-19 14:13:51] [INFO] [home:crawling:142] [crawling] Step 2: 정보 가공 시작...\n", "[2026-01-19 14:13:51] [INFO] [home:crawling:159] [crawling] Step 2 완료 - 오블로모프, 군산시 (0.8ms)\n", "[2026-01-19 14:13:51] [INFO] [home:crawling:163] [crawling] Step 3: ChatGPT 마케팅 분석 시작...\n", "[2026-01-19 14:13:51] [DEBUG] [home:crawling:170] [crawling] Step 3-1: 서비스 초기화 완료 (428.6ms)\n", "build_template \n", "[Role & Objective]\n", "Act as a content marketing expert with strong domain knowledge in the Korean pension / stay-accommodation industry.\n", "Your goal is to produce a Marketing Intelligence Report that will be shown to accommodation owners BEFORE any content is generated.\n", "The report must clearly explain what makes the property sellable, marketable, and scalable through content.\n", "\n", "[INPUT]\n", "- Business Name: {customer_name}\n", "- Region: {region}\n", "- Region Details: {detail_region_info}\n", "\n", "[Core Analysis Requirements]\n", "Analyze the property based on:\n", "Location, concept, and nearby environment\n", "Target customer behavior and reservation decision factors\n", "Include:\n", "- Target customer segments & personas\n", "- Unique Selling Propositions (USPs)\n", "- Competitive landscape (direct & indirect competitors)\n", "- Market positioning\n", "\n", "[Key Selling Point Structuring – UI Optimized]\n", "From the analysis above, extract the main Key Selling Points using the structure below.\n", "Rules:\n", "Focus only on factors that directly influence booking decisions\n", "Each selling point must be concise and visually scannable\n", "Language must be reusable for ads, short-form videos, and listing headlines\n", "Avoid full sentences in descriptions; use short selling phrases\n", "Do not provide in report\n", "\n", "Output format:\n", "[Category]\n", "(Tag keyword – 5~8 words, noun-based, UI oval-style)\n", "One-line selling phrase (not a full sentence)\n", "Limit:\n", "5 to 8 Key Selling Points only\n", "Do not provide in report\n", "\n", "[Content & Automation Readiness Check]\n", "Ensure that:\n", "Each tag keyword can directly map to a content theme\n", "Each selling phrase can be used as:\n", "- Video hook\n", "- Image headline\n", "- Ad copy snippet\n", "\n", "\n", "[Tag Generation Rules]\n", "- Tags must include **only core keywords that can be directly used for viral video song lyrics**\n", "- Each tag should be selected with **search discovery + emotional resonance + reservation conversion** in mind\n", "- The number of tags must be **exactly 5**\n", "- Tags must be **nouns or short keyword phrases**; full sentences are strictly prohibited\n", "- The following categories must be **balanced and all represented**:\n", " 1) **Location / Local context** (region name, neighborhood, travel context)\n", " 2) **Accommodation positioning** (emotional stay, private stay, boutique stay, etc.)\n", " 3) **Emotion / Experience** (healing, rest, one-day escape, memory, etc.)\n", " 4) **SNS / Viral signals** (Instagram vibes, picture-perfect day, aesthetic travel, etc.)\n", " 5) **Travel & booking intent** (travel, getaway, stay, relaxation, etc.)\n", "\n", "- If a brand name exists, **at least one tag must include the brand name or a brand-specific expression**\n", "- Avoid overly generic keywords (e.g., “hotel”, “travel” alone); **prioritize distinctive, differentiating phrases**\n", "- The final output must strictly follow the JSON format below, with no additional text\n", "\n", " \"tags\": [\"Tag1\", \"Tag2\", \"Tag3\", \"Tag4\", \"Tag5\"]\n", "\n", "input_data {'customer_name': '오블로모프', 'region': '군산시', 'detail_region_info': '전북 군산시 절골길 16'}\n", "[ChatgptService] Generated Prompt (length: 2791)\n", "[2026-01-19 14:13:51] [INFO] [chatgpt:generate_structured_output:43] [ChatgptService] Starting GPT request with structured output with model: gpt-5-mini\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:187] [crawling] Step 3-3: GPT API 호출 완료 - (63233.5ms)\n", "[2026-01-19 14:14:52] [DEBUG] [home:crawling:188] [crawling] Step 3-3: GPT API 호출 완료 - (63233.5ms)\n", "[2026-01-19 14:14:52] [DEBUG] [home:crawling:193] [crawling] Step 3-4: 응답 파싱 시작 - facility_info: 무선 인터넷, 예약, 주차\n", "[2026-01-19 14:14:52] [DEBUG] [home:crawling:212] [crawling] Step 3-4: 응답 파싱 완료 (2.1ms)\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:215] [crawling] Step 3 완료 - 마케팅 분석 성공 (63670.2ms)\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:229] [crawling] ========== COMPLETE ==========\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:230] [crawling] 총 소요시간: 64412.0ms\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:231] [crawling] - Step 1 (크롤링): 735.1ms\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:233] [crawling] - Step 2 (정보가공): 0.8ms\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:235] [crawling] - Step 3 (GPT 분석): 63670.2ms\n", "[2026-01-19 14:14:52] [INFO] [home:crawling:237] [crawling] - GPT API 호출: 63233.5ms\n" ] } ], "source": [ "var2 = await crawling(val1)" ] }, { "cell_type": "code", "execution_count": 7, "id": "79f093f0-d7d2-4ed1-ba43-da06e4ee2073", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'image_list': ['https://ldb-phinf.pstatic.net/20230515_163/1684090233619kRU3v_JPEG/20230513_154207.jpg',\n", " 'https://ldb-phinf.pstatic.net/20250811_213/17548982879808X4MH_PNG/1.png',\n", " 'https://ldb-phinf.pstatic.net/20240409_34/1712622373542UY8aC_JPEG/20231007_051403.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_37/1684090234513tT89X_JPEG/20230513_152018.jpg',\n", " 'https://ldb-phinf.pstatic.net/20241231_272/1735620966755B9XgT_PNG/DSC09054.png',\n", " 'https://ldb-phinf.pstatic.net/20240409_100/1712622410472zgP15_JPEG/20230523_153219.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_151/1712623034401FzQbd_JPEG/Screenshot_20240409_093158_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_169/1712622316504ReKji_JPEG/20230728_125946.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230521_279/1684648422643NI2oj_JPEG/20230521_144343.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_52/1712622993632WR1sT_JPEG/Screenshot_20240409_093237_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20250811_151/1754898220223TNtvB_PNG/2.png',\n", " 'https://ldb-phinf.pstatic.net/20240409_70/1712622381167p9QOI_JPEG/20230608_175722.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_144/1684090233161cR5mr_JPEG/20230513_180151.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_158/1712621983956CCqdo_JPEG/20240407_121826.jpg',\n", " 'https://ldb-phinf.pstatic.net/20250811_187/1754893113769iGO5X_JPEG/%B0%C5%BD%C7_01.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_31/17126219901822nnR4_JPEG/20240407_121615.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_94/1712621993863AWMKi_JPEG/20240407_121520.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_165/1684090236297fVhJM_JPEG/20230513_165348.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_102/1684090230350e1v0E_JPEG/20230513_162718.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_26/1684090232743arN2y_JPEG/20230513_174246.jpg',\n", " 'https://ldb-phinf.pstatic.net/20250811_273/1754893072358V3WcL_JPEG/%B5%F0%C5%D7%C0%CF%C4%C6_02.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_160/1712621974438LLNbD_JPEG/20240407_121848.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_218/1712623006036U39zE_JPEG/Screenshot_20240409_093114_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_210/16840902342654EkeL_JPEG/20230513_152107.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_216/1712623058832HBulg_JPEG/Screenshot_20240409_093309_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_184/1684090223226nO2Az_JPEG/20230514_143325.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_209/1684090697642BHNVR_JPEG/20230514_143528.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_16/1712623029052VNeaz_JPEG/Screenshot_20240409_093141_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_141/1684090233092KwtWy_JPEG/20230513_180105.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_177/1712623066424dcwJ2_JPEG/Screenshot_20240409_093511_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_181/16840902259407iA5Q_JPEG/20230514_144814.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_153/1684090224581Ih4ft_JPEG/20230514_143552.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_205/1684090231467WmulO_JPEG/20230513_180254.jpg',\n", " 'https://ldb-phinf.pstatic.net/20230515_120/1684090231233PkqCf_JPEG/20230513_152550.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_188/1712623039909sflvy_JPEG/Screenshot_20240409_093209_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_165/1712623049073j0TzM_JPEG/Screenshot_20240409_093254_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_3/17126230950579050V_JPEG/Screenshot_20240409_093412_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_270/1712623091524YX4E6_JPEG/Screenshot_20240409_093355_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_22/1712623083348btwTB_JPEG/Screenshot_20240409_093331_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_242/1712623087423Q7tHk_JPEG/Screenshot_20240409_093339_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_173/1712623098958aFhiB_JPEG/Screenshot_20240409_093422_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_113/1712623103270DOGKI_JPEG/Screenshot_20240409_093435_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_295/17126230704056BTRg_JPEG/Screenshot_20240409_093448_Airbnb.jpg',\n", " 'https://ldb-phinf.pstatic.net/20240409_178/1712623075172JEt43_JPEG/Screenshot_20240409_093457_Airbnb.jpg'],\n", " 'image_count': 44,\n", " 'processed_info': ProcessedInfo(customer_name='오블로모프', region='군산시', detail_region_info='전북 군산시 절골길 16'),\n", " 'marketing_analysis': MarketingAnalysis(report=MarketingAnalysisReport(summary=\"오블로모프는 '느림·쉼·문학적 감성'을 브랜드 콘셉트로 삼아 전북 군산시 절골길 인근의 조용한 주거·근대문화 접근성을 살린 소규모 부티크 스테이입니다. 도심형 접근성과 지역 근대문화·항구 관광지를 결합해 주말 단기체류, 커플·소규모 그룹, 콘텐츠 크리에이터 수요를 공략할 수 있습니다. 핵심은 브랜드 스토리(‘Oblomov’의 느긋함)와 인스타형 비주얼, 지역 연계 체험 상품으로 예약전환을 높이는 것입니다.\", details=[MarketingAnalysisDetail(detail_title='입지·콘셉트·주변 환경', detail_description='절골길 인근의 주택가·언덕형 지형, 조용한 체류 환경. 군산 근대역사문화거리·항구·현지 시장 접근권(차로 10–25분권). 문학적·레트로 감성 콘셉트(오블로모프 → 느림·휴식)으로 도심형 ‘감성 은신처’ 포지셔닝 가능.'), MarketingAnalysisDetail(detail_title='예약 결정 요인(고객 행동)', detail_description='사진·비주얼(첫 인상) → 콘셉트·프라이버시(전용공간 여부) → 접근성(차·대중교통 소요) → 가격 대비 가치·후기 → 체크인 편의성(셀프체크인 여부) → 지역 체험(먹거리·근대문화 투어) 순으로 예약 전환 영향.'), MarketingAnalysisDetail(detail_title='타깃 고객 세그먼트 & 페르소나', detail_description='1) 20–40대 커플: 주말 단기여행, 인생샷·감성 중심. 2) 20–30대 SNS 크리에이터/프리랜서: 콘텐츠·촬영지 탐색. 3) 소규모 가족·친구 그룹: 편안한 휴식·지역먹거리 체험. 4) 도심 직장인(원데이캉스): 근교 드라이브·힐링 목적.'), MarketingAnalysisDetail(detail_title='주요 USP(차별화 포인트)', detail_description='브랜드 스토리(‘Oblomov’ 느림의 미학), 군산 근대문화·항구 접근성, 소규모 부티크·프라이빗 체류감, 감성 포토존·인테리어로 SNS 확산 가능, 지역 먹거리·투어 연계로 체류 체감 가치 상승.'), MarketingAnalysisDetail(detail_title='경쟁 환경(직·간접 경쟁)', detail_description=\"직접: 군산 내 펜션·게스트하우스·한옥스테이(근대문화거리·항구 인근). 간접: 근교 글램핑·리조트·카페형 숙소, 당일투어(시장·박물관)로 체류대체 가능. 경쟁 우위는 '문학적 느림' 콘셉트+인스타블 친화적 비주얼.\"), MarketingAnalysisDetail(detail_title='시장 포지셔닝 제안', detail_description=\"중간 가격대의 부티크 스테이(가성비+감성), '주말 힐링·감성 촬영지' 중심 마케팅. 타깃 채널: 네이버 예약·에어비앤비·인스타그램·유튜브 숏폼. 지역 협업(카페·투어·해산물 체험)으로 패키지화.\")]), tags=['군산오블로모프', '부티크스테이', '힐링타임', '인생샷스팟', '주말여행'], facilities=['군산 근대거리·항구 근접', '문학적 느림·부티크 스테이', '프라이빗 객실·소규모 전용감', '감성 포토존·인테리어', '해산물·시장·근대투어 연계', '주말 단기여행·원데이캉스 수요'])}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "var2" ] }, { "cell_type": "code", "execution_count": 8, "id": "f3bf1d76-bd2a-43d5-8d39-f0ab2459701a", "metadata": {}, "outputs": [ { "ename": "KeyError", "evalue": "'selling_points'", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mKeyError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[43mvar2\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mselling_points\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m]\u001b[49m:\n\u001b[32m 2\u001b[39m \u001b[38;5;28mprint\u001b[39m(i[\u001b[33m'\u001b[39m\u001b[33mcategory\u001b[39m\u001b[33m'\u001b[39m])\n\u001b[32m 3\u001b[39m \u001b[38;5;28mprint\u001b[39m(i[\u001b[33m'\u001b[39m\u001b[33mkeywords\u001b[39m\u001b[33m'\u001b[39m])\n", "\u001b[31mKeyError\u001b[39m: 'selling_points'" ] } ], "source": [ "for i in var2[\"selling_points\"]:\n", " print(i['category'])\n", " print(i['keywords'])\n", " print(i['description'])" ] }, { "cell_type": "code", "execution_count": null, "id": "c89cf2eb-4f16-4dc5-90c6-df89191b4e39", "metadata": {}, "outputs": [], "source": [ "var2[\"selling_points\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "231963d6-e209-41b3-8e78-2ad5d06943fe", "metadata": {}, "outputs": [], "source": [ "var2[\"tags\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "f8260222-d5a2-4018-b465-a4943c82bd3f", "metadata": {}, "outputs": [], "source": [ "lyric_prompt = \"\"\"\n", "[ROLE]\n", "You are a content marketing expert, brand strategist, and creative songwriter\n", "specializing in Korean pension / accommodation businesses.\n", "You create lyrics strictly based on Brand & Marketing Intelligence analysis\n", "and optimized for viral short-form video content.\n", "\n", "[INPUT]\n", "Business Name: {customer_name}\n", "Region: {region}\n", "Region Details: {detail_region_info}\n", "Brand & Marketing Intelligence Report: {marketing_intelligence_summary}\n", "Output Language: {language}\n", "\n", "[INTERNAL ANALYSIS – DO NOT OUTPUT]\n", "Internally analyze the following to guide all creative decisions:\n", "- Core brand identity and positioning\n", "- Emotional hooks derived from selling points\n", "- Target audience lifestyle, desires, and travel motivation\n", "- Regional atmosphere and symbolic imagery\n", "- How the stay converts into “shareable moments”\n", "- Which selling points must surface implicitly in lyrics\n", "\n", "[LYRICS & MUSIC CREATION TASK]\n", "Based on the Brand & Marketing Intelligence Report for [{customer_name} ({region})], generate:\n", "- Original promotional lyrics\n", "- Music attributes for AI music generation (Suno-compatible prompt)\n", "The output must be designed for VIRAL DIGITAL CONTENT\n", "(short-form video, reels, ads).\n", "\n", "[LYRICS REQUIREMENTS]\n", "Mandatory Inclusions:\n", "- Business name\n", "- Region name\n", "- Promotion subject\n", "- Promotional expressions including:\n", "{promotional_expressions[language]}\n", "\n", "Content Rules:\n", "- Lyrics must be emotionally driven, not descriptive listings\n", "- Selling points must be IMPLIED, not explained\n", "- Must sound natural when sung\n", "- Must feel like a lifestyle moment, not an advertisement\n", "\n", "Tone & Style:\n", "- Warm, emotional, and aspirational\n", "- Trendy, viral-friendly phrasing\n", "- Calm but memorable hooks\n", "- Suitable for travel / stay-related content\n", "\n", "[SONG & MUSIC ATTRIBUTES – FOR SUNO PROMPT]\n", "After the lyrics, generate a concise music prompt including:\n", "Song mood (emotional keywords)\n", "BPM range\n", "Recommended genres (max 2)\n", "Key musical motifs or instruments\n", "Overall vibe (1 short sentence)\n", "\n", "[CRITICAL LANGUAGE REQUIREMENT – ABSOLUTE RULE]\n", "ALL OUTPUT MUST BE 100% WRITTEN IN {language}.\n", "no mixed languages\n", "All names, places, and expressions must be in {language} \n", "Any violation invalidates the entire output\n", "\n", "[OUTPUT RULES – STRICT]\n", "{timing_rules}\n", "8–12 lines\n", "Full verse flow, immersive mood\n", "\n", "No explanations\n", "No headings\n", "No bullet points\n", "No analysis\n", "No extra text\n", "\n", "[FAILURE FORMAT]\n", "If generation is impossible:\n", "ERROR: Brief reason in English\n", "\"\"\"\n", "lyric_prompt_dict = {\n", " \"prompt_variables\" :\n", " [\n", " \"customer_name\",\n", " \"region\",\n", " \"detail_region_info\",\n", " \"marketing_intelligence_summary\",\n", " \"language\",\n", " \"promotional_expression_example\",\n", " \"timing_rules\",\n", " \n", " ],\n", " \"output_format\" : {\n", " \"format\": {\n", " \"type\": \"json_schema\",\n", " \"name\": \"lyric\",\n", " \"schema\": {\n", " \"type\":\"object\",\n", " \"properties\" : {\n", " \"lyric\" : { \n", " \"type\" : \"string\"\n", " }\n", " },\n", " \"required\": [\"lyric\"],\n", " \"additionalProperties\": False,\n", " },\n", " \"strict\": True\n", " }\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": 4, "id": "79edd82b-6f4c-43c7-9205-0b970afe06d7", "metadata": {}, "outputs": [], "source": [ "\n", "with open(\"./app/utils/prompts/marketing_prompt.txt\", \"w\") as fp:\n", " fp.write(marketing_prompt)" ] }, { "cell_type": "code", "execution_count": 17, "id": "65a5a2a6-06a5-4ee1-a796-406c86aefc20", "metadata": {}, "outputs": [], "source": [ "with open(\"prompts/summarize_prompt.json\", \"r\") as fp:\n", " p = json.load(fp)" ] }, { "cell_type": "code", "execution_count": 18, "id": "454d920f-e9ed-4fb2-806c-75b8f7033db9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'prompt_variables': ['report', 'selling_points'],\n", " 'prompt': '\\n입력 : \\n분석 보고서\\n{report}\\n\\n셀링 포인트\\n{selling_points}\\n\\n위 분석 결과를 바탕으로, 주요 셀링 포인트를 다음 구조로 재정리하라.\\n\\n조건:\\n각 셀링 포인트는 반드시 ‘카테고리 → 태그 키워드 → 한 줄 설명’ 구조를 가질 것\\n태그 키워드는 UI 상에서 타원(oval) 형태의 시각적 태그로 사용될 것을 가정하여\\n- 3 ~ 6단어 이내\\n- 명사 또는 명사형 키워드로 작성\\n- 설명은 문장이 아닌, 짧은 ‘셀링 문구’ 형태로 작성할 것\\n- 광고·숏폼·상세페이지 어디에도 바로 재사용 가능해야 함\\n- 전체 셀링 포인트 개수는 5~7개로 제한\\n\\n출력 형식:\\n[카테고리명]\\n(태그 키워드)\\n- 한 줄 설명 문구\\n\\n예시: \\n[공간 정체성]\\n(100년 적산가옥 · 시간의 결)\\n- 하루를 ‘숙박’이 아닌 ‘체류’로 바꾸는 공간\\n\\n[입지 & 희소성]\\n(말랭이마을 · 로컬 히든플레이스)\\n- 관광지가 아닌, 군산을 아는 사람의 선택\\n\\n[프라이버시]\\n(독채 숙소 · 프라이빗 스테이)\\n- 누구의 방해도 없는 완전한 휴식 구조\\n\\n[비주얼 경쟁력]\\n(감성 인테리어 · 자연광 스폿)\\n- 찍는 순간 콘텐츠가 되는 공간 설계\\n\\n[타깃 최적화]\\n(커플 · 소규모 여행)\\n- 둘에게 가장 이상적인 공간 밀도\\n\\n[체류 경험]\\n(아무것도 안 해도 되는 하루)\\n- 일정 없이도 만족되는 하루 루틴\\n\\n[브랜드 포지션]\\n(호텔도 펜션도 아닌 아지트)\\n- 다시 돌아오고 싶은 개인적 장소\\n ',\n", " 'output_format': {'format': {'type': 'json_schema',\n", " 'name': 'tags',\n", " 'schema': {'type': 'object',\n", " 'properties': {'category': {'type': 'string'},\n", " 'tag_keywords': {'type': 'string'},\n", " 'description': {'type': 'string'}},\n", " 'required': ['category', 'tag_keywords', 'description'],\n", " 'additionalProperties': False},\n", " 'strict': True}}}" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p" ] }, { "cell_type": "code", "execution_count": 3, "id": "c46abcda-d6a8-485e-92f1-526fb28c6b53", "metadata": {}, "outputs": [], "source": [ "import json\n", "marketing_prompt_dict = {\n", " \"model\" : \"gpt-5-mini\",\n", " \"prompt_variables\" :\n", " [\n", " \"customer_name\",\n", " \"region\",\n", " \"detail_region_info\"\n", " ],\n", " \"output_format\" : {\n", " \"format\": {\n", " \"type\": \"json_schema\",\n", " \"name\": \"report\",\n", " \"schema\": {\n", " \"type\" : \"object\",\n", " \"properties\" : {\n", " \"report\" : {\n", " \"type\": \"object\",\n", " \"properties\" : {\n", " \"summary\" : {\"type\" : \"string\"},\n", " \"details\" : {\n", " \"type\" : \"array\",\n", " \"items\" : {\n", " \"type\": \"object\",\n", " \"properties\" : {\n", " \"detail_title\" : {\"type\" : \"string\"},\n", " \"detail_description\" : {\"type\" : \"string\"},\n", " },\n", " \"required\": [\"detail_title\", \"detail_description\"],\n", " \"additionalProperties\": False,\n", " }\n", " }\n", " },\n", " \"required\" : [\"summary\", \"details\"],\n", " \"additionalProperties\" : False\n", " },\n", " \"selling_points\" : {\n", " \"type\": \"array\",\n", " \"items\": {\n", " \"type\": \"object\",\n", " \"properties\" : {\n", " \"category\" : {\"type\" : \"string\"},\n", " \"keywords\" : {\"type\" : \"string\"},\n", " \"description\" : {\"type\" : \"string\"}\n", " },\n", " \"required\": [\"category\", \"keywords\", \"description\"],\n", " \"additionalProperties\": False,\n", " },\n", " },\n", " \"tags\" : {\n", " \"type\": \"array\",\n", " \"items\": {\n", " \"type\": \"string\"\n", " },\n", " },\n", " \"contents_advise\" : {\"type\" : \"string\"}\n", " },\n", " \"required\": [\"report\", \"selling_points\", \"tags\", \"contents_advise\"],\n", " \"additionalProperties\": False,\n", " },\n", " \"strict\": True\n", " }\n", " }\n", "}\n", "with open(\"./app/utils/prompts/marketing_prompt.json\", \"w\") as fp:\n", " json.dump(marketing_prompt_dict, fp, ensure_ascii=False)" ] }, { "cell_type": "code", "execution_count": 15, "id": "c3867dab-0c4e-46be-ad12-a9c02b5edb68", "metadata": {}, "outputs": [], "source": [ "lyric_prompt = \"\"\"\n", "[ROLE]\n", "You are a content marketing expert, brand strategist, and creative songwriter\n", "specializing in Korean pension / accommodation businesses.\n", "You create lyrics strictly based on Brand & Marketing Intelligence analysis\n", "and optimized for viral short-form video content.\n", "\n", "[INPUT]\n", "Business Name: {customer_name}\n", "Region: {region}\n", "Region Details: {detail_region_info}\n", "Brand & Marketing Intelligence Report: {marketing_intelligence_summary}\n", "Output Language: {language}\n", "\n", "[INTERNAL ANALYSIS – DO NOT OUTPUT]\n", "Internally analyze the following to guide all creative decisions:\n", "- Core brand identity and positioning\n", "- Emotional hooks derived from selling points\n", "- Target audience lifestyle, desires, and travel motivation\n", "- Regional atmosphere and symbolic imagery\n", "- How the stay converts into “shareable moments”\n", "- Which selling points must surface implicitly in lyrics\n", "\n", "[LYRICS & MUSIC CREATION TASK]\n", "Based on the Brand & Marketing Intelligence Report for [{customer_name} ({region})], generate:\n", "- Original promotional lyrics\n", "- Music attributes for AI music generation (Suno-compatible prompt)\n", "The output must be designed for VIRAL DIGITAL CONTENT\n", "(short-form video, reels, ads).\n", "\n", "[LYRICS REQUIREMENTS]\n", "Mandatory Inclusions:\n", "- Business name\n", "- Region name\n", "- Promotion subject\n", "- Promotional expressions including:\n", "{promotional_expressions[language]}\n", "\n", "Content Rules:\n", "- Lyrics must be emotionally driven, not descriptive listings\n", "- Selling points must be IMPLIED, not explained\n", "- Must sound natural when sung\n", "- Must feel like a lifestyle moment, not an advertisement\n", "\n", "Tone & Style:\n", "- Warm, emotional, and aspirational\n", "- Trendy, viral-friendly phrasing\n", "- Calm but memorable hooks\n", "- Suitable for travel / stay-related content\n", "\n", "[SONG & MUSIC ATTRIBUTES – FOR SUNO PROMPT]\n", "After the lyrics, generate a concise music prompt including:\n", "Song mood (emotional keywords)\n", "BPM range\n", "Recommended genres (max 2)\n", "Key musical motifs or instruments\n", "Overall vibe (1 short sentence)\n", "\n", "[CRITICAL LANGUAGE REQUIREMENT – ABSOLUTE RULE]\n", "ALL OUTPUT MUST BE 100% WRITTEN IN {language}.\n", "no mixed languages\n", "All names, places, and expressions must be in {language} \n", "Any violation invalidates the entire output\n", "\n", "[OUTPUT RULES – STRICT]\n", "{timing_rules}\n", "8–12 lines\n", "Full verse flow, immersive mood\n", "\n", "No explanations\n", "No headings\n", "No bullet points\n", "No analysis\n", "No extra text\n", "\n", "[FAILURE FORMAT]\n", "If generation is impossible:\n", "ERROR: Brief reason in English\n", "\"\"\"\n", "with open(\"./app/utils/prompts/lyric_prompt.txt\", \"w\") as fp:\n", " fp.write(lyric_prompt)" ] }, { "cell_type": "code", "execution_count": 14, "id": "5736ca4b-c379-4cae-84a9-534cad9576c7", "metadata": {}, "outputs": [], "source": [ "lyric_prompt_dict = {\n", " \"model\" : \"gpt-5-mini\",\n", " \"prompt_variables\" :\n", " [\n", " \"customer_name\",\n", " \"region\",\n", " \"detail_region_info\",\n", " \"marketing_intelligence_summary\",\n", " \"language\",\n", " \"promotional_expression_example\",\n", " \"timing_rules\",\n", " \n", " ],\n", " \"output_format\" : {\n", " \"format\": {\n", " \"type\": \"json_schema\",\n", " \"name\": \"lyric\",\n", " \"schema\": {\n", " \"type\":\"object\",\n", " \"properties\" : {\n", " \"lyric\" : { \n", " \"type\" : \"string\"\n", " }\n", " },\n", " \"required\": [\"lyric\"],\n", " \"additionalProperties\": False,\n", " },\n", " \"strict\": True\n", " }\n", " }\n", "}\n", "with open(\"./app/utils/prompts/lyric_prompt.json\", \"w\") as fp:\n", " json.dump(lyric_prompt_dict, fp, ensure_ascii=False)" ] }, { "cell_type": "code", "execution_count": null, "id": "430c8914-4e6a-4b53-8903-f454e7ccb8e2", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.8" } }, "nbformat": 4, "nbformat_minor": 5 }