import os import pandas as pd import gradio as gr from datetime import datetime import openai ############################## # [LLM자료] 에서 제공된 코드 시작 ############################## # OpenAI API 클라이언트 설정 openai.api_key = os.getenv("OPENAI_API_KEY") def call_api(content, system_message, max_tokens, temperature, top_p): response = openai.ChatCompletion.create( model="gpt-4o-mini", # 반드시 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'] ############################## # [LLM자료] 에서 제공된 코드 끝 ############################## ############################## # [기본코드] 시작 (수정 및 삭제 불가) ############################## 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] # 1차 옵션 추출 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) # 상위 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)) return positive_output def get_negative_reviews(df): negative_reviews = df[df['ReviewScore'] <= 2].sort_values(by='Review Length', ascending=False) negative_reviews = negative_reviews.head(30) # 상위 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)) return negative_output def process_reviews(file): df = read_excel_data(file) positive_reviews = get_positive_reviews(df) negative_reviews = get_negative_reviews(df) return positive_reviews, negative_reviews ############################## # [기본코드] 끝 (수정 및 삭제 불가) ############################## # LLM 분석을 위한 헬퍼 함수 def analyze_with_llm(review_content, system_prompt): # review_content: 긍정 혹은 부정 리뷰 텍스트 # system_prompt: 시스템 역할 프롬프트 analysis_result = call_api( content=review_content, system_message=system_prompt, max_tokens=500, temperature=0.7, top_p=1.0 ) return analysis_result # 리뷰를 추출한 뒤, 자동으로 LLM 분석까지 수행 def process_reviews_and_analyze(file): # 기존 리뷰 추출 positive_reviews, negative_reviews = process_reviews(file) # 긍정 리뷰 분석 system_prompt_positive = ( "당신은 전문 리뷰 분석가입니다. 아래에는 긍정 리뷰들이 나열되어 있습니다.\n" "이 리뷰들에서 고객이 만족해하는 주요 포인트와 특징을 요약해주고, " "추가적인 인사이트를 제시해 주세요." ) positive_analysis = analyze_with_llm(positive_reviews, system_prompt_positive) # 부정 리뷰 분석 system_prompt_negative = ( "당신은 전문 리뷰 분석가입니다. 아래에는 부정 리뷰들이 나열되어 있습니다.\n" "이 리뷰들에서 고객이 불만을 가지는 주요 포인트와 특징을 요약해주고, " "개선점을 제시해 주세요." ) negative_analysis = analyze_with_llm(negative_reviews, system_prompt_negative) return positive_reviews, negative_reviews, positive_analysis, 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) gr.Markdown("### 부정적인 주요 리뷰 (최대 30개)") negative_reviews_output = gr.Textbox(label="부정적인 주요 리뷰", interactive=False, lines=30) # LLM 분석 결과를 표시할 영역 gr.Markdown("### 긍정 리뷰 분석 결과") positive_analysis_output = gr.Textbox(label="긍정 리뷰 분석", interactive=False, lines=7) gr.Markdown("### 부정 리뷰 분석 결과") negative_analysis_output = gr.Textbox(label="부정 리뷰 분석", interactive=False, lines=7) # 리뷰 추출 + LLM 분석까지 한 번에 수행 analyze_button.click( fn=process_reviews_and_analyze, inputs=[file_input], outputs=[ positive_reviews_output, negative_reviews_output, positive_analysis_output, negative_analysis_output ] ) return demo if __name__ == "__main__": interface = create_interface() interface.launch()