import os import pandas as pd import gradio as gr import openai from datetime import datetime # OpenAI API 클라이언트 설정 openai.api_key = os.getenv("OPENAI_API_KEY") # LLM 호출 함수 def call_api(content, system_message, max_tokens=2000, temperature=0.7, top_p=0.9): response = openai.ChatCompletion.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": system_message}, {"role": "user", "content": content}, ], max_tokens=max_tokens, temperature=temperature, top_p=top_p, ) return response.choices[0].message['content'] # 엑셀 데이터 읽기 함수 def read_excel_data(file): df = pd.read_excel(file, usecols="A, B, C, D, E", skiprows=1, names=["ID", "Review Date", "Option", "Review", "ReviewScore"], engine='openpyxl') df['Review Date'] = pd.to_datetime(df['Review Date']).dt.tz_localize(None).dt.date df['Year'] = df['Review Date'].astype(str).str.slice(0, 4) df['Option1'] = df['Option'].astype(str).str.split(" / ").str[0] df['Review Length'] = df['Review'].str.len() return df # 긍정적인 리뷰를 반환하는 함수 def get_positive_reviews(df): positive_reviews = df[df['ReviewScore'] >= 4].sort_values(by='Review Length', ascending=False) positive_reviews = positive_reviews.head(20) positive_reviews.reset_index(drop=True, inplace=True) positive_reviews.index += 1 positive_reviews['순번'] = positive_reviews.index positive_output = "\n\n".join(positive_reviews.apply( lambda x: f"{x['순번']}. **{x['Review Date']} / {x['ID']} / {x['Option']}**\n\n{x['Review']}", axis=1)) system_message = """[중요 규칙] 1. 반드시 한글(한국어)로 출력하라. 2. 너는 리뷰 데이터를 분석하는 빅데이터 분석가이다. 3. 고객의 리뷰 데이터를 바탕으로 긍정적인 의견의 데이터만 분석하라. 4. 반드시 제공된 리뷰 데이터에서만 분석하라. 5. 너의 생각을 포함하지 말 것. [분석 조건] 1. 총 20개의 리뷰데이터를 제공한다. 2. 각 리뷰 데이터의 둘째줄 부터의 실제 고객리뷰를 반영하라. 3. 반드시 긍정적인 의견만을 분석하라. 부정적인 의견은 제외하라. 4. 기능과 성능의 부분, 감성적인 부분, 실제 사용 측면의 부분, 배송의 부분, 타겟별 부분의 관점으로 분석하라. 5. 4번의 조건에 포함되지 않는 긍정적인 리뷰를 별도로 출력하라. 6. 마케팅적인 요소로 사용할 수 있는 고객의 실제 리뷰를 반영하라. [출력 형태 조건] 1. 각각의 제목 앞에 '📝'이모지를 출력하라,'#', '##'은 출력하지 말것. 2. 가장 마지막에 종합 의견을 작성하라, "🏆종합의견"의 제목형태를 사용하라. [종합의견의 출력 조건 시작] ('종합의견'이 아닌 다른 부분에 이 출력 조건을 반영하지 말 것. - 항목별 제목을 제외하라. - 종합의견에는 항목별 제목을 제외하고 서술식 문장으로 작성하라. - 매출을 극대화 할 수 있는 고객의 실제 리뷰 포인트를 제시하라. [SWOT분석 조건] 1. '종합의견' 다음 내용으로 SWOT분석 의견을 출력하라. 2. SWOT분석 중 '강점'의견과 '기회'의 의견을 출력하라. 3. 반드시 '종합의견'의 내용을 기반으로 작성하라. 4. 제목은 '🏹 강점', '🏹 기회'으로 출력하라. [종합의견의 출력 조건 끝] 3. 실제 고객의 리뷰 데이터에서 사용된 단어를 포함하라. 4. 너의 생각을 임의로 넣지 말 것. """ analysis = call_api(positive_output, system_message=system_message) return positive_output, analysis # 부정적인 리뷰를 반환하는 함수 def get_negative_reviews(df): negative_reviews = df[df['ReviewScore'] <= 2].sort_values(by='Review Length', ascending=False) negative_reviews = negative_reviews.head(30) negative_reviews.reset_index(drop=True, inplace=True) negative_reviews.index += 1 negative_reviews['순번'] = negative_reviews.index negative_output = "\n\n".join(negative_reviews.apply( lambda x: f"{x['순번']}. **{x['Review Date']} / {x['ID']} / {x['Option']}**\n\n{x['Review']}", axis=1)) system_message = """[중요 규칙] 1. 반드시 한글(한국어)로 출력하라. 2. 너는 리뷰 데이터를 분석하는 빅데이터 분석가이다. 3. 고객의 리뷰 데이터를 바탕으로 부정적인 의견의 데이터만 분석하라. 4. 반드시 제공된 리뷰 데이터에서만 분석하라. 5. 너의 생각을 포함하지 말 것. [분석 조건] 1. 총 30개의 리뷰데이터를 제공한다. 2. 각 리뷰 데이터의 둘째줄 부터의 실제 고객리뷰를 반영하라. 3. 부정적인 의견만을 분석하라. 4. 기능과 성능의 부분, 감성적인 부분, 실제 사용 측면의 부분, 배송의 부분, 고객의 분노 부분의 관점으로 분석하라. 5. 4번의 조건에 포함되지 않는 부정적인 리뷰를 별도로 출력하라. 6. 부정적인 리뷰 분석 결과를 바탕으로 '개선할 점'을 출력하라. [출력 형태 조건] 1. 각각의 제목 앞에 '📝'이모지를 출력하라,'#', '##'은 출력하지 말것. 2. 가장 마지막에 '개선할 점'을 출력하라("📢개선할 점"의 제목형태를 사용하라.) [개선할 점의 출력 조건 시작] ('개선할 점'이 아닌 다른 부분에 이 출력 조건을 반영하지 말 것. - 항목별 제목을 제외하라. - 주요 항목별로 개선할 점을 출력하라. - 전문적이고, 분석적이며, 제안하는 형태의 공손한 어투를 사용하라.(단답형 표현 금지) [SWOT분석 조건] 1. '종합의견' 다음 내용으로 SWOT분석 의견을 출력하라. 2. SWOT분석 중 '약점'의견과 '위협'의 의견을 출력하라. 3. 반드시 '개선할 점'의 내용을 기반으로 작성하라. 4. 제목은 '💉 약점', '💉 위협'으로 출력하라. [개선할 점의 출력 조건 끝] 3. 실제 고객의 리뷰 데이터에서 사용된 단어를 포함하라. 4. 너의 생각을 임의로 넣지 말 것. """ analysis = call_api(negative_output, system_message=system_message) return negative_output, analysis # 리뷰 데이터를 처리하여 긍정 및 부정 리뷰를 추출하는 함수 def process_reviews(file): df = read_excel_data(file) positive_reviews, positive_analysis = get_positive_reviews(df) negative_reviews, negative_analysis = get_negative_reviews(df) return positive_reviews, positive_analysis, negative_reviews, negative_analysis # Gradio 인터페이스 구성 def create_interface(): with gr.Blocks() as demo: gr.Markdown("### 리뷰 데이터 업로드 및 분석") file_input = gr.File(label="엑셀 파일 업로드", file_types=[".xlsx"]) analyze_button = gr.Button("리뷰분석") with gr.Column(): gr.Markdown("### 긍정적인 주요 리뷰 (최대 20개)") positive_reviews_output = gr.Textbox(label="긍정적인 주요 리뷰", interactive=False, lines=20) positive_analysis_output = gr.Textbox(label="긍정 리뷰 분석 결과", interactive=False, lines=10) gr.Markdown("### 부정적인 주요 리뷰 (최대 30개)") negative_reviews_output = gr.Textbox(label="부정적인 주요 리뷰", interactive=False, lines=30) negative_analysis_output = gr.Textbox(label="부정 리뷰 분석 결과", interactive=False, lines=10) analyze_button.click( fn=process_reviews, inputs=[file_input], outputs=[positive_reviews_output, positive_analysis_output, negative_reviews_output, negative_analysis_output] ) return demo if __name__ == "__main__": interface = create_interface() interface.launch()