Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from datetime import datetime | |
| import re | |
| def extract_month_from_period(period_text): | |
| """이벤트 기간에서 월 추출""" | |
| if not period_text or period_text.strip() == "": | |
| return None | |
| date_patterns = [ | |
| r'(\d{4})\.(\d{1,2})\.(\d{1,2})', | |
| r'(\d{1,2})\.(\d{1,2})', | |
| r'(\d{1,2})월', | |
| ] | |
| for pattern in date_patterns: | |
| matches = re.findall(pattern, period_text) | |
| if matches: | |
| if len(matches[0]) == 3: | |
| month = int(matches[0][1]) | |
| elif len(matches[0]) == 2: | |
| month = int(matches[0][0]) | |
| else: | |
| month = int(matches[0]) | |
| if 1 <= month <= 12: | |
| return f"{month}월" | |
| return None | |
| def analyze_concepts(month): | |
| """20-40대 여성 맞춤 월별 컨셉 분석""" | |
| monthly_data = { | |
| "1월": { | |
| "special_days": ["미니멀 챌린지", "새해 리셋", "플래너 스타트"], | |
| "trends": ["미니멀", "자기계발", "플래너", "정리정돈"], | |
| "colors": ["#FF6B6B", "#4ECDC4", "#45B7D1"], | |
| "mood": "희망적이고 새로운 시작", | |
| "female_appeal": ["미니멀", "자기계발", "셀프케어"] | |
| }, | |
| "2월": { | |
| "special_days": ["갈렌타인데이", "셀프러브", "사랑의 달"], | |
| "trends": ["셀프러브", "갈렌타인", "로맨스", "따뜻한 감성"], | |
| "colors": ["#FF69B4", "#FFB6C1", "#DC143C"], | |
| "mood": "로맨틱하고 감성적", | |
| "female_appeal": ["셀프러브", "우정", "로맨스"] | |
| }, | |
| "3월": { | |
| "special_days": ["여성의 날", "봄의 시작", "새학기"], | |
| "trends": ["봄맞이", "벚꽃 시즌", "봄 패션", "새출발"], | |
| "colors": ["#FFB6C1", "#98FB98", "#87CEEB"], | |
| "mood": "설렘가득하고 활기찬", | |
| "female_appeal": ["봄 패션", "꽃구경", "새출발"] | |
| }, | |
| "4월": { | |
| "special_days": ["벚꽃 시즌", "봄나들이", "피크닉"], | |
| "trends": ["벚꽃축제", "봄피크닉", "아웃도어", "꽃놀이"], | |
| "colors": ["#98FB98", "#F0E68C", "#DDA0DD"], | |
| "mood": "생기발랄하고 즐거운", | |
| "female_appeal": ["벚꽃놀이", "피크닉", "봄여행"] | |
| }, | |
| "5월": { | |
| "special_days": ["로즈데이", "감사의 달", "힐링"], | |
| "trends": ["감사", "나들이", "로즈데이", "봄여행"], | |
| "colors": ["#32CD32", "#FFB6C1", "#87CEEB"], | |
| "mood": "따뜻하고 감사한", | |
| "female_appeal": ["로즈데이", "감사표현", "힐링"] | |
| }, | |
| "6월": { | |
| "special_days": ["키스데이", "여름 준비", "쿨링"], | |
| "trends": ["여름준비", "쿨링", "바캉스준비", "여름패션"], | |
| "colors": ["#00CED1", "#FFD700", "#FF6347"], | |
| "mood": "시원하고 활동적인", | |
| "female_appeal": ["여름준비", "쿨링케어", "바캉스"] | |
| }, | |
| "7월": { | |
| "special_days": ["실버데이", "여름휴가", "바캉스"], | |
| "trends": ["여름휴가", "바캉스", "휴가패션", "여행"], | |
| "colors": ["#00BFFF", "#FFD700", "#FF6347"], | |
| "mood": "역동적이고 자유로운", | |
| "female_appeal": ["바캉스", "여행", "휴가패션"] | |
| }, | |
| "8월": { | |
| "special_days": ["그린데이", "여름 마무리", "휴가"], | |
| "trends": ["여름휴가", "바다여행", "축제", "여름추억"], | |
| "colors": ["#00BFFF", "#FF6347", "#FFD700"], | |
| "mood": "열정적이고 추억가득한", | |
| "female_appeal": ["여름추억", "힐링", "여행"] | |
| }, | |
| "9월": { | |
| "special_days": ["포토데이", "뮤직데이", "가을시작"], | |
| "trends": ["가을패션", "독서", "문화생활", "감성"], | |
| "colors": ["#FF8C00", "#DC143C", "#B8860B"], | |
| "mood": "감성적이고 성숙한", | |
| "female_appeal": ["가을패션", "카페", "독서"] | |
| }, | |
| "10월": { | |
| "special_days": ["와인데이", "커피데이", "독서의 달"], | |
| "trends": ["가을단풍", "독서", "카페문화", "와인"], | |
| "colors": ["#FF8C00", "#DC143C", "#B8860B"], | |
| "mood": "감성적이고 여유로운", | |
| "female_appeal": ["단풍구경", "카페", "와인"] | |
| }, | |
| "11월": { | |
| "special_days": ["무비데이", "오렌지데이", "연말준비"], | |
| "trends": ["빼빼로데이", "연말준비", "겨울패션", "따뜻함"], | |
| "colors": ["#8B4513", "#A0522D", "#CD853F"], | |
| "mood": "포근하고 준비하는", | |
| "female_appeal": ["빼빼로데이", "겨울패션", "연말모임"] | |
| }, | |
| "12월": { | |
| "special_days": ["허그데이", "연말파티", "송년"], | |
| "trends": ["크리스마스", "연말파티", "선물", "송년회"], | |
| "colors": ["#DC143C", "#228B22", "#FFD700"], | |
| "mood": "축제같고 따뜻한", | |
| "female_appeal": ["크리스마스", "연말모임", "선물"] | |
| } | |
| } | |
| data = monthly_data.get(month, {}) | |
| concepts = [] | |
| # 컨셉 1 | |
| if data.get("special_days"): | |
| special = data["special_days"][0] | |
| concepts.append({ | |
| "name": f"{special} 이벤트", | |
| "theme": f"{special}를 테마로 한 여성 맞춤 이벤트", | |
| "score": 8.8, | |
| "reason": f"20-40대 여성이 공감할 수 있는 {special} 테마", | |
| "target": "20-40대 여성", | |
| "colors": data.get("colors", ["#FF69B4"]), | |
| "keywords": [special] + data.get("female_appeal", [])[:2], | |
| "is_recommended": True | |
| }) | |
| # 컨셉 2 | |
| if data.get("trends"): | |
| trend = data["trends"][0] | |
| concepts.append({ | |
| "name": f"{trend} 챌린지", | |
| "theme": f"{trend} 트렌드 참여형 이벤트", | |
| "score": 8.0, | |
| "reason": f"인기 {trend} 트렌드로 높은 관심도", | |
| "target": "20-30대 트렌드 민감층", | |
| "colors": data.get("colors", ["#4ECDC4"]), | |
| "keywords": data.get("trends", [])[:3], | |
| "is_recommended": False | |
| }) | |
| # 컨셉 3 | |
| concepts.append({ | |
| "name": f"{month} 셀프케어 위크", | |
| "theme": "나를 위한 특별한 시간", | |
| "score": 8.3, | |
| "reason": "셀프케어로 강한 어필", | |
| "target": "20-40대 여성", | |
| "colors": data.get("colors", ["#FFB6C1"]), | |
| "keywords": ["셀프케어", "힐링", "나를 위한 시간"], | |
| "is_recommended": True | |
| }) | |
| concepts.sort(key=lambda x: (x.get("is_recommended", False), x["score"]), reverse=True) | |
| recommended_concept = next((c for c in concepts if c.get("is_recommended", False)), concepts[0]) | |
| result = f"# 🎯 {month} 20-40대 여성 맞춤 컨셉 분석\n\n" | |
| result += f"## 🏆 이달의 추천 컨셉: {recommended_concept['name']}\n" | |
| result += f"**⭐ 추천 이유:** {recommended_concept['reason']}\n" | |
| result += f"**📊 예상 참여도:** {recommended_concept['score']}/10점\n\n" | |
| result += "---\n\n" | |
| concept_names = [] | |
| for i, concept in enumerate(concepts, 1): | |
| is_recommended_mark = " 🏆 **추천**" if concept.get("is_recommended", False) else "" | |
| result += f"## {i}. {concept['name']}{is_recommended_mark}\n" | |
| result += f"**🏷️ 테마:** {concept['theme']}\n" | |
| result += f"**⭐ 참여도 점수:** {concept['score']}/10점\n" | |
| result += f"**💡 선정 이유:** {concept['reason']}\n" | |
| result += f"**🎯 주요 타겟:** {concept['target']}\n" | |
| result += f"**🔑 핵심 키워드:** {', '.join(concept['keywords'])}\n" | |
| result += f"**🎨 추천 색상:** {', '.join(concept['colors'])}\n\n" | |
| result += "---\n\n" | |
| concept_names.append(concept['name']) | |
| return result, concept_names | |
| def generate_design_recommendations(concept_name, month): | |
| """디자인 추천""" | |
| design_styles = { | |
| "미니멀": ["심플 미니멀 디자인", "깔끔한 선과 여백을 활용"], | |
| "네온사인": ["레트로 네온사인 스타일", "80년대 네온사인 화려함"], | |
| "Y2K": ["Y2K 레트로 퓨처", "2000년대 미래적 감성"], | |
| "게임UI": ["게임 인터페이스", "RPG 게임 UI 모티브"] | |
| } | |
| monthly_design = { | |
| "1월": ["미니멀", "Y2K"], "2월": ["미니멀", "네온사인"], | |
| "3월": ["네온사인", "Y2K"], "4월": ["네온사인", "Y2K"], | |
| "5월": ["미니멀", "네온사인"], "6월": ["네온사인", "Y2K"], | |
| "7월": ["Y2K", "네온사인"], "8월": ["Y2K", "게임UI"], | |
| "9월": ["미니멀", "네온사인"], "10월": ["미니멀", "네온사인"], | |
| "11월": ["미니멀", "네온사인"], "12월": ["네온사인", "게임UI"] | |
| } | |
| month_key = month.replace('월', '월') | |
| recommended_designs = monthly_design.get(month_key, ["미니멀", "네온사인"]) | |
| result = "## 🎨 추천 디자인 스타일\n\n" | |
| for i, design_key in enumerate(recommended_designs, 1): | |
| if design_key in design_styles: | |
| style_name, description = design_styles[design_key] | |
| result += f"### {i}. {style_name} 🌟\n" | |
| result += f"**설명:** {description}\n\n" | |
| return result | |
| def generate_trendy_copy(concept_name, month): | |
| """트렌디한 카피라이팅 생성""" | |
| trendy_copies = { | |
| "미니멀": { | |
| "sub1": "🌟 '나는 정리를 못하는 여자'는 이제 그만!", | |
| "main": "미니멀은 '미'니로 '말'하는 거야, 작게 말해도 큰 변화! ✨", | |
| "sub2": "올해는 진짜 '갓생'을 살아보자구요! 💪", | |
| "hashtags": ["#갓생살기", "#미니멀", "#정리의신", "#새해정리"] | |
| }, | |
| "그린데이": { | |
| "sub1": "💚 '그린'하면 생각나는 게 뭐예요?", | |
| "main": "그린데이는 '그'냥 '린'스하지 말고 새롭게! 💚", | |
| "sub2": "이번 여름엔 '그린'한 추억 만들어요 🌿", | |
| "hashtags": ["#그린데이", "#여름추억", "#힐링", "#자연"] | |
| }, | |
| "셀프케어": { | |
| "sub1": "💕 '나 자신과 연애 중'이라고 말할 수 있나요?", | |
| "main": "셀프케어는 '셀프'로 '케어'하는 거 맞아! 💖", | |
| "sub2": "오늘부터 내가 내 최고의 친구가 되는 거야 ✨", | |
| "hashtags": ["#셀프케어", "#나를위한시간", "#힐링", "#자기사랑"] | |
| } | |
| } | |
| # 기본 카피 | |
| default_copy = { | |
| "sub1": "✨ 이런 특별한 순간을 놓칠 수 없죠!", | |
| "main": "지금 이 순간이 바로 '찐'이야! 💫", | |
| "sub2": "함께라면 뭐든 '레전드'가 될 수 있어요 🎉", | |
| "hashtags": ["#찐이야", "#레전드순간", "#함께해요", "#특별한시간"] | |
| } | |
| # 컨셉명에서 키워드 찾기 | |
| for keyword, copy_data in trendy_copies.items(): | |
| if keyword in concept_name: | |
| return copy_data | |
| return default_copy | |
| def generate_notice(concept, event_type, event_period, prize_benefits): | |
| """공지사항 생성""" | |
| if not concept: | |
| return "먼저 컨셉을 선택해주세요." | |
| # 이벤트 기간 설정 | |
| if not event_period or event_period.strip() == "": | |
| now = datetime.now() | |
| start_date = now.strftime("%Y.%m.%d") | |
| end_date = f"{now.year}.{now.month}.{now.day + 7}" | |
| period_text = f"{start_date} ~ {end_date}" | |
| else: | |
| period_text = event_period | |
| # 월 추출 | |
| month = extract_month_from_period(period_text) | |
| if not month: | |
| month = f"{datetime.now().month}월" | |
| # 카피 생성 | |
| copy_data = generate_trendy_copy(concept, month) | |
| # 디자인 추천 | |
| design_recommendations = generate_design_recommendations(concept, month) | |
| # 당첨 혜택 설정 | |
| if not prize_benefits or prize_benefits.strip() == "": | |
| benefits_text = """✨ 1등 (1명): 스타벅스 5만원 기프트카드 | |
| 🎉 2등 (3명): 베스킨라빈스 아이스크림 쿠폰 | |
| 💝 3등 (10명): 편의점 5천원 상품권 | |
| 🌟 참가상 (50명): 모바일 치킨 쿠폰""" | |
| else: | |
| benefits_text = prize_benefits | |
| # 해시태그 | |
| hashtags_text = " ".join(copy_data['hashtags']) | |
| notice = f"""{copy_data['sub1']} | |
| 💫 {copy_data['main']} 💫 | |
| {copy_data['sub2']} | |
| 🎉 {concept} 🎉 | |
| 📅 이벤트 기간: {period_text} 23:59 | |
| {hashtags_text} | |
| {design_recommendations} | |
| ======================== | |
| ✨ EVENT | |
| 특별한 {concept}을 준비했어요! | |
| 많은 분들의 적극적인 참여를 기다리고 있습니다 💕 | |
| 이번 이벤트는 단순한 참여가 아닌, | |
| 우리만의 특별한 추억을 만들어가는 시간이에요 ✨ | |
| ======================== | |
| 🎯 참여 방법 | |
| 1️⃣ 이벤트 내용 확인하기 | |
| 2️⃣ {event_type} 참여하기 | |
| 3️⃣ 참여 완료! | |
| ================= | |
| 🎁 당첨혜택 | |
| {benefits_text} | |
| 📋 추첨: 참여자 중 무작위 추첨 | |
| ======================== | |
| 👥 이벤트 대상 | |
| ✅ 커뮤니티 회원 | |
| ✅ 만 18세 이상 | |
| ✅ 이벤트 기간 내 참여자 | |
| ======================== | |
| ⚠️ 주의사항 | |
| ※ 부적절한 참여는 제외됩니다 | |
| ※ 중복 참여 불가 | |
| ※ 당첨자는 본인 확인 필요 | |
| =========================== | |
| 📞 문의: 1234-5678 | |
| 💬 카카오톡: @event_community | |
| {hashtags_text} | |
| 💝 많은 참여 부탁드려요! 감사합니다 💝""" | |
| return notice | |
| def create_interface(): | |
| """그라디오 인터페이스 생성""" | |
| with gr.Blocks(title="이벤트 공지사항 생성기") as demo: | |
| gr.Markdown("# 🎉 이벤트 공지사항 생성기") | |
| gr.Markdown("### 20-40대 여성 맞춤 트렌디한 이벤트를 만들어보세요!") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("## 설정") | |
| event_period_input = gr.Textbox( | |
| label="이벤트 기간", | |
| placeholder="예: 2025.8.1 ~ 2025.8.10", | |
| info="이벤트 기간을 입력하면 해당 월이 자동으로 선택됩니다" | |
| ) | |
| month_dropdown = gr.Dropdown( | |
| choices=[f"{i}월" for i in range(1, 13)], | |
| label="이벤트 월 선택", | |
| value="1월" | |
| ) | |
| analyze_btn = gr.Button("컨셉 분석하기", variant="primary") | |
| concept_dropdown = gr.Dropdown( | |
| label="컨셉 선택", | |
| visible=False | |
| ) | |
| event_type_dropdown = gr.Dropdown( | |
| choices=["댓글 달기", "게시글 작성", "좋아요 누르기"], | |
| label="이벤트 유형", | |
| value="댓글 달기" | |
| ) | |
| gr.Markdown("## 🎁 당첨 혜택 설정") | |
| prize_benefits_input = gr.Textbox( | |
| label="당첨 혜택", | |
| placeholder="당첨 혜택을 입력하세요 (비워두면 기본 혜택 적용)", | |
| lines=6 | |
| ) | |
| generate_btn = gr.Button("공지사항 생성하기", variant="secondary", visible=False) | |
| with gr.Column(): | |
| gr.Markdown("## 결과") | |
| concept_output = gr.Textbox( | |
| label="컨셉 분석 결과", | |
| lines=20, | |
| placeholder="먼저 '컨셉 분석하기' 버튼을 클릭하세요" | |
| ) | |
| notice_output = gr.Textbox( | |
| label="생성된 공지사항", | |
| lines=25, | |
| placeholder="컨셉을 선택하고 '공지사항 생성하기' 버튼을 클릭하세요" | |
| ) | |
| # 상태 변수 | |
| concepts_state = gr.State([]) | |
| selected_concept_state = gr.State("") | |
| def handle_period_change(period_text): | |
| detected_month = extract_month_from_period(period_text) | |
| if detected_month: | |
| return gr.update(value=detected_month) | |
| return gr.update() | |
| def handle_analyze(month): | |
| result, concepts = analyze_concepts(month) | |
| return ( | |
| result, | |
| gr.update(choices=concepts, visible=True, value=concepts[0]), | |
| gr.update(visible=True), | |
| concepts | |
| ) | |
| def handle_concept_change(concept, concepts): | |
| return concept | |
| def handle_generate(concept, event_type, event_period, prize_benefits): | |
| notice = generate_notice(concept, event_type, event_period, prize_benefits) | |
| return notice | |
| # 이벤트 연결 | |
| event_period_input.change( | |
| handle_period_change, | |
| inputs=[event_period_input], | |
| outputs=[month_dropdown] | |
| ) | |
| analyze_btn.click( | |
| handle_analyze, | |
| inputs=[month_dropdown], | |
| outputs=[concept_output, concept_dropdown, generate_btn, concepts_state] | |
| ) | |
| concept_dropdown.change( | |
| handle_concept_change, | |
| inputs=[concept_dropdown, concepts_state], | |
| outputs=[selected_concept_state] | |
| ) | |
| generate_btn.click( | |
| handle_generate, | |
| inputs=[selected_concept_state, event_type_dropdown, event_period_input, prize_benefits_input], | |
| outputs=[notice_output] | |
| ) | |
| return demo | |
| if __name__ == "__main__": | |
| demo = create_interface() | |
| demo.launch() |