import gradio as gr import os import asyncio import aiohttp from dotenv import load_dotenv load_dotenv() openai_api_key = os.getenv("OPENAI_API_KEY") # OpenAI API 비동기 호출 함수 async def call_openai_api_async(session, prompts, max_tokens, temperature, top_p): try: async with session.post( "https://api.openai.com/v1/chat/completions", headers={"Authorization": f"Bearer {openai_api_key}"}, json={ "model": "gpt-4o-mini", "messages": prompts, "max_tokens": max_tokens, "temperature": temperature, "top_p": top_p, } ) as response: result = await response.json() if 'choices' not in result: print("Unexpected API response:", result) return "API 응답 오류" return result['choices'][0]['message']['content'] except Exception as e: print(f"API 호출 중 오류 발생: {str(e)}") return "API 호출 오류" # 전체 분석 함수 (비동기) async def analyze_all_async(combined_output, progress=gr.Progress()): async with aiohttp.ClientSession() as session: tasks = [] for label, setting in settings.items(): prompts_item = [ {"role": "system", "content": setting["system_message"]}, {"role": "user", "content": combined_output} ] task = asyncio.create_task(call_openai_api_async( session, prompts_item, setting["max_tokens"], setting["temperature"], setting["top_p"] )) tasks.append((label, task)) results = {} total_steps = len(settings) completed_tasks = 0 for label, task in tasks: try: result = await task results[label] = result except Exception as e: print(f"API 호출 중 오류 발생 ({label}): {str(e)}") results[label] = "API 호출 오류" completed_tasks += 1 progress((completed_tasks / total_steps), desc="분석 중...") progress(1.0, desc="분석 완료!") return results # 개별 분석 함수 (비동기) async def analyze_single_async(combined_output, analysis_type, progress=gr.Progress()): async with aiohttp.ClientSession() as session: setting = settings.get(analysis_type) if not setting: return "올바르지 않은 분석 타입" prompts_single = [ {"role": "system", "content": setting["system_message"]}, {"role": "user", "content": combined_output} ] result = await call_openai_api_async( session, prompts_single, setting["max_tokens"], setting["temperature"], setting["top_p"] ) return result # 개별 분석 래퍼 함수 생성기 def get_analyze_single_wrapper(analysis_type): async def wrapper(combined_output): result = await analyze_single_async(combined_output, analysis_type) return result return wrapper # 입력값들을 결합하는 함수 def generate_combined_output(product, nuance, target, features, reviews): # 기본값 설정 product_placeholder = "초음파 가습기" nuance_placeholder = "기능적 중심 분석" target_placeholder = "일반인" features_placeholder = """ [제품 정보] 1. 제품의 브랜드는 (ETS 가습기)입니다. 2. ETS의 브랜드 가치는 (청정의 약속을 담다)를 잘 녹였으면 좋겠습니다. 3. 제품의 장점(스펙) 1) 3단계 분무량 조절가능 - 1단계: 100ml, 2단계: 200ml, 3단계: 300ml 2) 대용량 수조로 3일 이상 보충 없이 사용 가능 - 4.2L (대용량 수조) 3) 가습력이 경쟁사보다 풍부 - 최대가습량 : 300ml 4) 세척 관리가 매우 쉽다. - 분리형 구조 (간편 세척) 5) 습도조절센서를 활용하여 자동으로 조절 및 OFF가 가능 - AI 자동 습도 조절, 타이머 기능 6) 물 보충이 매우 쉽다. - 상부 구조 급수 방식 7) 가열식 가습기에 비해 에너지 소비 낮음, 소음 적음, 가열을 하지 않아 안전함 - 초음파 가습기 조용 8) 믿을 수 있는 국내 제작 및 AS - 국내 제작""" reviews_placeholder = """ [리뷰] 1. 매우 만족합니다. 가습량도 많고 세척도 편리해요. 2. 다른 제품에 비해 소음이 적고 디자인도 예뻐요. 3. 물 보충이 쉽고 오래 사용 가능해서 좋아요. """ product = product if product else product_placeholder nuance = nuance if nuance else nuance_placeholder target = target if target else target_placeholder features = features if features else features_placeholder reviews = reviews if reviews else reviews_placeholder combined_output = f"Product: {product}\nNuance: {nuance}\nTarget Audience: {target}\nFeatures: {features}\nReviews: {reviews}" return combined_output # ★ UI 리셋 함수 (각 컴포넌트의 update 메서드를 사용) def ui_reset_all(): # reset 순서: [product_input (Textbox), # nuance_options (Dropdown), # target_options (Dropdown), # features_input (Textbox), # reviews_input (Textbox), # combined_output (Textbox)] + # [각 프롬프트별 출력(Textbox) (len(prompts)개)] + # [final_output (Textbox)] resets = [] resets.append(gr.Textbox.update(value="")) # product_input resets.append(gr.Dropdown.update(value="예제를 선택해보세요")) # nuance_options resets.append(gr.Dropdown.update(value="예제를 선택해보세요")) # target_options resets.append(gr.Textbox.update(value="")) # features_input resets.append(gr.Textbox.update(value="")) # reviews_input resets.append(gr.Textbox.update(value="")) # combined_output resets.extend([gr.Textbox.update(value="") for _ in range(len(prompts))]) # 각 프롬프트별 출력 resets.append(gr.Textbox.update(value="")) # final_output return tuple(resets) # 프롬프트 정의 prompts = { "1️⃣회사 슬로건": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 세계적으로 유명한 마케터이자, 카피라이터이다. 3. 상세페이지를 만들려고 한다. 항목은 "slogan."이다. 4. 정보를 바탕으로 긍정적인 메세지와 강력한 임팩트가 있는 문구를 작성하라. 5. 2줄 이내로 간략하게 작성하라. 6. 10가지 슬로건을 출력하라.(결과물 앞에 번호를 출력하라) 7. 상품명(상품키워드)는 제외하라. 8. Target을 반드시 반영하라. 9. 읽기 쉽고, 기억하기 쉽게 작성하라. 10. [좋은 슬로건의 원칙]을 참고하라. [출력형식] 1. 슬로건 10개 이외에는 다른 어떤 내용도 출력하지 말 것. 2. 일차원적, 직관적 언어로 작성하라. [좋은 슬로건의 원칙] 1. 간결성 : 짧고 간결해야한다. "Just Do It"처럼 단 몇 개의 단어로도 큰 의미를 담을 수 있어야 한다. 2. 명료성 : 명료해야한다. 아무리 멋진 문장이라도 그 의미가 모호하다면 사람들은 그 브랜드를 기억하기 어렵다. - 따라서 단어 선택이 중요하다, 명료한 메세지로 인지도를 높여야한다. 3. 기억력 : 기억하기 쉬워야한다. 좋은 슬로건은 사람들이 한번 들어도 잊지 못하게 만드는 매력이 있다. 4. 제품의 가장 핵심적인 포인트를 담는다. 5. 핵심 가치나 비전을 나타낼 수 있는 키워드나 표현을 찾는다. 6. 감정적인연결 요소를 만든다. [실제 사용중인 슬로건 예시] 1. 핀크: "알아서 챙겨주는 나만의 머니 트레이너" 2. 디즈니랜드: "지구에서 가장 행복한 곳" 3. 밀리의 서재: "독서가 취미가 되는 당신을 만나보세요" 4. 삼성 그랑데 건조기: "우리가 키운건 단지 건조기의 크기가 아니라 깨끗함의 크기" 5. 노스페이스: "올 겨울 우리의 심장은 함께 뛴다" 6. 뉴라미스: "얼굴은. 웃을때. 가장 매력적이다. 피부속까지 웃자!" 7. 파워에이드: "경기는 계속되어야 한다." 8. 오뚜기: "카레가 맛있어야 카레가 맛있지요" 9. 유한킴벌리 닥터마밍: "엄마와 닥터가 아기물티슈를 연구합니다" 10. 마켓컬리: "장보기를 새롭게, 퀄리티 있게" 11. 옥션: "옥션의 법칙 : 파는 사람들이 경쟁하면 가격은 내려갑니다" """, "2️⃣상품을 대표하는 문구": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 당신은 유명한 마케터이자, 카피라이터이다. 3. 출력 되는 모든 내용은 '매슬로우의 욕구 5단계' 관점에 맞도록 [출력형식]에 맞도록 카피를 생성하라 4. 반드시 상품명(상품키워드)는 제외하라. 5. 언어적인 느낌은 대한민국(한국)에서 쓰는 느낌으로 생성하라. 6. 핵심 메시지 1가지씩을 반영하라. 7. '카피라이팅 포인트'를 반영하라. 8. Target을 반드시 반영하라. [카피라이팅 포인트] 1. 호기심을 자극하라. 2. 유용한 정보를 제공하라. 3. 질문 형식으로 작성하라. 4. 감성을 자극하라. 5. 얻게될 이점을 명확하게 표현하라. 6. 놓치면 손해되는 포인트를 제시하라. 7. 반드시 상품명(상품키워드)는 제외하라. 8. 감성적이고 은유적인 표현으로 출력하라. [매슬로우의 욕구 5단계] 1. 생리적 욕구 2. 안전의 욕구 3. 사랑과 소속의 욕구 4. 존경의 욕구 5. 자아실현의 욕구 [출력형식] 1. 매슬로우의 욕구 5단계의 각 항목마다 5개씩 결과를 출력하라. 2. 반드시 상품명(상품키워드)는 제외하라. 3. 중국어(한자), 일본어(히라가나)는 제외하라. [예시] 1. 매일매일 청량하고 가볍게 즐겨요! """, "3️⃣이런분들에게 추천합니다": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 고액매출의 온라인 판매자이며 유명한 마케터이다. 3. 상품 판매를 촉진시키기 위한 상세페이지를 작성 한다. 항목은 "이런분들에게 추천합니다."이다. 4. 반드시 제공한 정보를 바탕으로 20개 작성하라. 5. Target을 반영하라. [출력 조건] 1. 제공된 데이터를 바탕으로 타겟이 얻게될 이점을 명확하게 표현하라. 2. 각 항목마다 마지막 문장에 "~분", "~분에게 추천" 으로 자연스럽게 끝나도록 생성하라. 3. 반드시 문장 앞쪽의 내용과 어울리도록 문장 뒤쪽에 타겟 대상을 배치하라. 4. 반드시 한줄로 작성하라(최대 35자) 5. 제공된 데이터와 [예시]를 바탕으로 20개 생성하라 [출력 금지 조건] 1. 절대로 '출력 금지 조건'에 있는 형태로 문장을 작성하지 말 것. 2. '부부분(부부+분)'처럼 자연스럽지 않은 한국어 3. '합니다', '~다', '~요'의 형태 4. 'A/S', '보증서', '손편지'등의 이점이 포함된 문장. 5. '아이 키우는 주부', '신혼부부', '선물용' 등의 단순한 타겟 6. '출력 금지 조건'에 해당되면 문장을 출력하지 말라. [예시] 1. 자동습도 조절기능이 필요하신분 2. 청소 및 관리가 편리한 제품을 찾으시는 분 3. 곰팡이 걱정 없이 사용할 수 있는 식기건조대가 필요하신분 4. 저녁 시간에도 조용하게 청소기를 돌리고 싶은 맞벌이 부부에게 추천 5. 스마트한 맵핑 기능으로 효율적인 청소를 하고 싶은 분 """, "4️⃣이런것 아세요?": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 인터넷 기사을 요약하고 정리하는 언론사 편집장이다. 3. 반드시 제공된 데이터를 바탕으로 공포마케팅 카피라이팅을 작성하라. 4. 반드시 대한민국(한국)에서 사용하는 언어적 표현으로 작성하라. [출력형식] 1. 각 카피당 30자 내외로 30개 생성하라. 2. 반드시 10개 이상은 구체적 수치를 포함하라. 3. 공포 마케팅(Fear marketing)을 하기 위한 헤드카피를 작성하라. 4. [공포마케팅 방법], [공포마케팅 활용사례]를 참고하여 헤드카피를 작성하라. 5. 질병유발, 증상, 위험요소, 안전요소등에 수치를 넣어서 주의가 필요하다는것을 더욱 강조하여 헤드카피를 생성하라. 6. 카피외에 다른 말은 출력하지 말라. 7. 맨 앞에 순번을 표시하라. 8. 출력 제외 조건에 해당되는 문장은 출력하지 말 것. [출력 제외 조건 시작] 1. 긍정적인 늉앙스(nuance)의 문장 2. 예시 : "99% 세균 제거"로 안심 세차하세요! 3. 예시 : "세균의 온상" 세차장, 간편 세차로 예방하세요! [출력 제외 조건 끝] [공포마케팅 방법] 1단계 : 고객이 현재 위험에 노출되어 있음을 알린다. 2단계 : 고객이 현재 노출된 위험으로부터 벗어나려면 행동을 취해야 한다는 점을 알린다. 3단계 : 고객을 위험으로부터 보호해 줄 구체적인 행동을 알려준다. 4단계 : 고객이 이러한 구체적인 행동을 할 수 있도록 자극한다. [공포마케팅 활용사례] 1. 여성용 면도기 : 여성의 노출이 많아지는 패션이 유행하면서 겨드랑이 털을 제모하는 흐름이 생겨났고, 질레트는 이 기회를 노려 겨드랑이 털과 불쾌감을 연결하였습니다. 겨드랑이 털을 남에게 보이는 것은 비매너이거나 게으른 것처럼 공포 마케팅을 진행하였고 이를 통해서 여성용 면도기 및 제모 상품의 매출이 크게 증가하였습니다. 2. 탈모샴푸 : 탈모샴푸를 마케팅할 때 그 제품의 효능과 효과를 더욱 어필하기보다는 사용하지 않았을 때 생기는 불이익을 언급함으로써 우리의 공포심을 자극합니다. '이 샴푸는 ~한 성분이 들어있습니다.'보다는 '이 샴푸를 사용하지 않고 방치한다면 친구들에 비해 10년은 나이 들어 보일 수 있습니다.'처럼 제품을 사용하지 않았을 때 발생할 수 있는 불이익을 강조하여 사람들의 반응을 이끌어 냅니다. 3. 구강청결제 : 구강청결제는 기존에 없던 새로운 위협요소를 성공적으로 어필한 사례에 해당합니다. 미국의 대표적인 구강청결제인 리스테린은 처음 출시되었을 때 광고를 통해 사람들 사이에서 입 냄새로 인하여 대인관계가 악화되는 모습을 지속적으로 보여주었습니다. 그리고 지독한 입 냄새로 인해서 사람들이 자신을 나쁘게 평가할 수 있다는 두려움을 파고들어 마케팅에 성공할 수 있었습니다. [예시] 1. 가습기 2일만 관리하지 않아도 "세균 범벅" 2. 바다 환경오염, 식탁으로 되돌아온다. 플라스틱 사용 이대로 괜찮은가요? 3. "맥주 한잔이라도 날마다 술이 땡긴다면? 이것 의심해야" 4. 하루에 밥 한 공기만 줄여도 오래 산다는 연구결과도 있고, 서울대병원 암센터의 암예방 10계명 중에도 '적절한 체중관리'가 포함되어 있다. 5. 5살 아이의 눈에 손세정제가 들어가 각막이 벗겨지는 사고 6. "오염수 소식 들었죠? 암보험 들어두세요" 7. 주방 세균, "2배" 빠른 속도로 증식! 우리 집은 안전지대? 8. "200배" 강한 세균, 우리 집 식기건조대에? """, "5️⃣이 상품 사용후 이렇게 달라졌어요": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 당신은 제품을 구매하고 실제로 사용한 후 너무 만족한 고객이다. 3. 출력 되는 모든 내용은 USP(Unique Selling Proposition)관점으로 작성하라. 4. "이 제품을 사용 후 만족하는 부분을 표현하고, 실생활이 얼마나, 어떻게 변했는지"를 작성하라. 5. 변화된 포인트를 강조하여 작성하라. 6. 제공된 실제 리뷰 데이터에서 장점(좋은 점)을 반영하여 작성하라. [출력조건] 1. 모든 출력 결과는 반드시 사실(데이터기반)이어야 한다. 2. 각 후기별 한줄 제목을 먼저 생성하고 그 아래에 인터뷰 답변 형태의 후기를 작성하라. 3. 인터뷰 제목에만 적절하고 이모지를 사용하라(이모지가 중복되지 않도록 하라) - 인터뷰 답변 내용에는 이모지를 사용하지 말 것. 4. '#', '##'은 출력하지 말것. 5. 반드시한국어(한글)로 출력하라. 6. 중국어(한자), 일본어(히라가나)는 제외하라. [출력형식] 1. 생생하고 긍정적인 인터뷰 답변 형태의 후기를 작성하라. - 질문은 출력하지 말라. 2. "🎤 감성적인 관점의 인터뷰" 후기 5개 생성하라. 3. "🎤 기능적인 관점의 인터뷰" 후기 5개 생성하라. 4. "🎤 타켓 맞춤 인터뷰" 후기 5개 생성하라. - 제공된 데이터를 기반으로 이 제품의 가장 적합한 타겟을 예측하여 그에 맞는 인터뷰 후기를 5개 생성하라. """, "6️⃣상품 설명": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 고액매출의 온라인 판매자이며 유명한 마케터이다. 3. 상품의 온라인 판매를 촉진시키기 위해 상세페이지를 제작한다. 4. 고객이 어떤 제품을 구매할지 고민할때 고민하는 항목을 질문으로 역제안 하는 방식이다. 5. 10개씩 2개 주제, 총 20개의 답변 이외에는 다른 답변을 하지 말 것. [출력조건] 1. 중국어(한자), 일본어는 제외하라. 2. [제품을 선택하실 때 어떤항목을 체크하시나요?]과 [어떤 제품을 구입하고 싶으세요?]의 주제로 작성하라. 3. 반드시 제공된 데이터의 내용만 반영하라. 4. 이점을 강조하고, 실제 경험을 공유하도록 작성하라. [제품을 선택하실 때 어떤항목을 체크하시나요?] 1. 반드시 마지막 문장에 "주나요?", "하나요?", "있나요?", "않나요"로 끝내라 2. 20~35자로 10개를 작성하라. 3. 순번을 작성하라. 4. 입력된 정보를 바탕으로 기능적 포인트를 강조하라. 5. 마케팅 포인트를 반영하라. 6. 제품의 차별점을 반영하라. [예시] - 세척관리가 편하나요? - 3일 이상 사용가능한가요? - 국내제작인가요? - 화재로부터 안전한가요? - 유해성분 없이 안전한가요? - 손에 닿아도 안전한가요? - 아기가 있는 곳에서도 괜찮나요? [어떤 제품을 구입하고 싶으세요?] 1. 반드시 마지막 문장에 "좋겠어요", "필요해요", "인거요", "원해요","싶어요","찾아요"로 끝내라 2. 20~35자로 10개를 작성하라. 3. 순번을 작성하라. 4. 입력된 정보를 바탕으로 기능적 포인트를 강조하라. 5. 마케팅 포인트를 반영하라. 6. 제품의 차별점을 반영하라. [예시] - 한번 세착하려면 힘이드는데 세척이 편했으면 좋겠어요 - 소음이 크지 않았으면 좋겠어요 - 분무량이 조정되었으면 좋겠어요 - 녹이 생기지 않고 반영구적으로 사용이 가능하면 좋겠어요 - 모기 및 해충을 빠르게 퇴치하면 좋겠어요 - 360도 전방향 사용이 가능한 제품을 찾아 - 디자인도 예쁘고 성능도 좋은 제품이 필요해요 """, "7️⃣상품 설명[자세히]": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 고액매출의 온라인 판매자이며 유명한 마케터이다. 3. 출력 되는 모든 내용은 USP(Unique Selling Proposition)관점으로 작성하라. 4. 차별화 시킬 수 있는 참신하고 폭발적이며, 매혹적이게 입력된 정보를 기반 작성하라. 5. 출력되는 언어의 표현은 대한민국(한국)에서 사용되는 느낌으로 작성하라. [출력조건] 1. 아마존닷컴에서 고객이 hook될 수 있도록 매우 강한 카피라이팅을 10개를 생성하라. 2. 메인카피(30자 내외), 서브카피(100자 내외)로 작성하라. 3. '메인카피', '서브카피' 단어는 제외하라. 4. 중국어(한자), 일본어(히라가나, 가타카나)는 제외하라. 5. '#', '##'은 제외하라. [출력예시] 1. 프로청소러의 비법, 드리미! - 맞벌이 부부와 주부의 고민을 해결해주는 드리미! 프로청소러의 비법을 공개합니다! 2. 드리미로 대충 청소할래요! - 대충 청소해도 먼지, 물걸레, 건조가 완벽! 청소하는 척, 그럴싸하게! 3. 로긴이 선물하는 편리한 주방 라이프 - 맞벌이 부부와 주부님들의 고민을 해결해드립니다! 로긴 식기건조대는 대용량 수납은 물론, 물받이 호환과 편리한 물빠짐 기능으로 설거지 후 건조까지 한 번에 편리하게! 이제 로긴과 함께 편리한 주방 라이프를 즐기세요! """, "8️⃣고객의 생생한 후기": """[중요 프롬프트] 1. 반드시 한국어로 출력하라. 2. 너는 유명한 온라인 콘텐츠 마케팅 대행사를 운영하는 대표이자 마케터다. 3. 마케팅에 도움이 되는, 고객이 필요로 하는 기능적 중심으로 제품후기를 생성하라. 4. 고객 후기는 진짜 고객이 사용하는 느낌이 들 수 있도록 작성하고, 인위적인 느낌이 나지 않고 반복적인 단어가 없도록하며, 솔직하고 실감나게 한국인이 작성한 것처럼 자연스러운 인터넷 커뮤니티에서 사용하는 문장으로 표현하라. 5. 기능을 너무 자세하게 설명하지 말고, 이런 기능을 사용하니 이런 부분이 좋았다(만족)의 느낌으로 작성해야한다. 6. 입력된 정보를 바탕으로 참고하여[50~100자] 내외로 10개의 후기를 작성하라. 7. 너의 소개는 하지 말 것. [출력형식] 1. 반드시 제공된 리뷰 데이터의 한국어 표현 형태를 반영하라. 2. 반드시 제공된 리뷰 데이터의 실제 리뷰를 반영하라. 3. 판매자가 아닌 실제 구매하여 사용한 사용자의 입장에서 작성하라. 4. 판매자가 홍보하는 형태가 아닌 사용자가 만족한 형태로 작성하라. 5. 예상 QnA를 반영하여 출력하라.(반드시 제공된 리뷰 데이터의 내용으로만 작성하라) 6. 사용전과 사용후의 포인트를 강조하라. 7. 적절한 이모지를 제목 가장 앞에 출력하라. [출력예시] 👨‍👩‍👧‍👦 아이 있는 집 필수템! 청소가 즐거워! - 아이를 키우다 보니 청결에 더 신경을 쓰게 되었는데, 드리미 L10s pro를 만나고 청소가 즐거워졌어요. 물걸레와 진공청소가 동시에 되니 바닥이 늘 깨끗하고, 특히 모서리나 구석까지 꼼꼼하게 청소해줘서 만족스러워요. 맵핑 기능으로 청소할 공간을 지정할 수도 있고, 물걸레와 진공청소 모드를 따로 설정할 수도 있어서 너무 편리해요. 아이 있는 집에 꼭 추천하고 싶어요! 🏘 복층 구조도 문제없어요! 청소가 쉬워졌어요! - 복층 구조의 집에서 사용하기 위해 드리미 L10s pro를 구매했어요. 층별 지도 생성은 물론, 가상벽 설정까지 가능해서 우리 집 구조를 완벽하게 파악하더니 구석구석 청소를 꼼꼼하게 해줘요. 특히, 물걸레가 말라붙은 자국까지 깨끗하게 닦아내서 항상 바닥이 깔끔해요. 복층 구조의 집에도 안성맞춤인 청소기예요! """ } # 설정값 딕셔너리 (각 프롬프트에 대한 API 호출 설정) settings = { label: { "system_message": prompts[label], "max_tokens": 4000, "temperature": 0.8, "top_p": 0.95 } for label in prompts } # Gradio 인터페이스 구성 with gr.Blocks() as demo: with gr.Row(): gr.Markdown("# 상품상세페이지 기획문구 생성기") with gr.Row(): # 왼쪽 컬럼: 입력 영역 with gr.Column(scale=6): gr.Markdown("## 입력") gr.Markdown("#### 1단계: 대표팀의 상품을 적어주세요 (자세히 작성해주세요)") gr.Markdown('

[예시: 가습기(X) / 초음파 가습기(O)]

') product_input = gr.Textbox(placeholder="초음파 가습기", show_label=False) gr.Markdown("
") gr.Markdown("#### 2단계: 분석 뉘앙스를 정해주세요 [아래 예시 참조]") gr.Markdown('

[설명 : 정하지 않으면 기능 중심으로 분석됩니다.]

') nuance_options = gr.Dropdown( choices=["예제를 선택해보세요", "기능적 중심 분석", "디자인 중심 분석", "감성적 중심 분석"], value="예제를 선택해보세요", show_label=False ) gr.Markdown("
") gr.Markdown("#### 3단계: 고객의 타겟을 정해주세요 [아래 예시 참조]") gr.Markdown('

[설명 : 자세한 고객타겟 설정도 가능합니다.]

') target_options = gr.Dropdown( choices=["예제를 선택해보세요", "대학생", "30,40대 직장인", "주부", "어린아이의 건강이 걱정되는 40대 주부"], value="예제를 선택해보세요", show_label=False ) gr.Markdown("
") gr.Markdown("#### 4단계: 동일한 상품 또는 비슷한 상품의 리뷰를 1~3개 정도를 넣어주세요") gr.Markdown('

[설명 : 쿠팡의 리뷰를 입력하는 것을 추천드립니다.]

') reviews_input = gr.Textbox(placeholder="리뷰를 입력하세요", lines=5, show_label=False) gr.Markdown("
") gr.Markdown("#### 5단계: 상품의 기능 또는 스펙 또는 장점을 자세히 작성해주세요") gr.Markdown('

[설명 : 자세한 내용을 입력할수록 분석이 잘됩니다.]

') features_input = gr.Textbox( placeholder="상품의 기능, 스펙, 장점을 입력하세요", show_label=False, ) gr.Markdown("
") combined_output = gr.Textbox(label="모든 입력값", lines=8) generate_button = gr.Button("생성") analyze_all_button = gr.Button("전체분석") reset_button = gr.Button("초기화") progress_bar = gr.Progress() # 오른쪽 컬럼: 출력 영역 (각 프롬프트별 탭 + 종합결과) with gr.Column(scale=6): gr.Markdown("## 출력") output_vars = {} reanalyze_buttons = {} for label in prompts.keys(): with gr.Tab(label): output = gr.Textbox(label=label, interactive=False, lines=12) reanalyze_button = gr.Button("개별 재분석") output_vars[label] = output reanalyze_buttons[label] = reanalyze_button with gr.Tab("9️⃣종합결과"): final_output = gr.Textbox(label="9️⃣종합결과", lines=20, interactive=False) # 입력값 변경 시 결합 텍스트 업데이트 def update_combined_output(product, nuance, target, features, reviews): return generate_combined_output(product, nuance, target, features, reviews) product_input.change( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) nuance_options.change( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) target_options.change( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) features_input.change( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) reviews_input.change( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) generate_button.click( update_combined_output, inputs=[product_input, nuance_options, target_options, features_input, reviews_input], outputs=combined_output ) # 전체 분석 버튼 (모든 항목 동시에 분석) async def analyze_all_wrapper(combined_output): try: results = await analyze_all_async(combined_output, progress=progress_bar) return [results.get(label, "분석 실패") for label in prompts.keys()] except Exception as e: print(f"전체 분석 중 오류 발생: {str(e)}") return ["분석 실패"] * len(prompts) analyze_all_button.click( fn=analyze_all_wrapper, inputs=[combined_output], outputs=[output_vars[label] for label in prompts.keys()] ) # 리셋 버튼: ui_reset_all()를 사용하여 각 컴포넌트를 올바르게 업데이트 reset_button.click( fn=ui_reset_all, inputs=[], outputs=[product_input, nuance_options, target_options, features_input, reviews_input, combined_output] + [output for output in output_vars.values()] + [final_output] ) # 종합 결과 업데이트 (각 항목 변경 시 종합결과 탭 업데이트) def update_final_output(*outputs): final_output_text = "" for label, output in zip(prompts.keys(), outputs): final_output_text += f"{label}\n{output}\n\n" return final_output_text for output in output_vars.values(): output.change( fn=update_final_output, inputs=list(output_vars.values()), outputs=final_output ) # 각 탭 내 "개별 재분석" 버튼에 대해 클릭 시 해당 항목만 재분석 for label, button in reanalyze_buttons.items(): button.click( fn=get_analyze_single_wrapper(label), inputs=[combined_output], outputs=output_vars[label] ) if __name__ == "__main__": demo.launch()