Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import gradio as gr
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
|
| 7 |
+
# 환경 변수 로드
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
# OpenAI API 키 설정 (현재는 사용하지 않지만 필요 시 유지)
|
| 11 |
+
openai_api_key = os.getenv("OPENAI_API_KEY")
|
| 12 |
+
|
| 13 |
+
# 엑셀 데이터 읽기 함수
|
| 14 |
+
def read_excel_data(file):
|
| 15 |
+
df = pd.read_excel(file, usecols="A, B, C, D, E", skiprows=1,
|
| 16 |
+
names=["ID", "Review Date", "Option", "Review", "ReviewScore"], engine='openpyxl')
|
| 17 |
+
df['Review Date'] = pd.to_datetime(df['Review Date']).dt.tz_localize(None).dt.date
|
| 18 |
+
df['Year'] = df['Review Date'].astype(str).str.slice(0, 4)
|
| 19 |
+
df['Option1'] = df['Option'].astype(str).str.split(" / ").str[0] # 1차 옵션 추출
|
| 20 |
+
df['Review Length'] = df['Review'].str.len() # 리뷰 길이 계산
|
| 21 |
+
return df
|
| 22 |
+
|
| 23 |
+
# 긍정적인 리뷰를 반환하는 함수
|
| 24 |
+
def get_positive_reviews(df):
|
| 25 |
+
# 리뷰 점수가 4 이상인 긍정 리뷰 필터링
|
| 26 |
+
positive_reviews = df[df['ReviewScore'] >= 4].sort_values(by='Review Length', ascending=False)
|
| 27 |
+
positive_reviews = positive_reviews.head(20) # 상위 20개 리뷰 선택
|
| 28 |
+
|
| 29 |
+
positive_reviews.reset_index(drop=True, inplace=True)
|
| 30 |
+
positive_reviews.index += 1
|
| 31 |
+
positive_reviews['순번'] = positive_reviews.index
|
| 32 |
+
|
| 33 |
+
# 리뷰 형식 지정
|
| 34 |
+
positive_output = "\n\n".join(positive_reviews.apply(
|
| 35 |
+
lambda x: f"{x['순번']}. **{x['Review Date']} / {x['ID']} / {x['Option']}**\n\n{x['Review']}", axis=1))
|
| 36 |
+
return positive_output
|
| 37 |
+
|
| 38 |
+
# 부정적인 리뷰를 반환하는 함수
|
| 39 |
+
def get_negative_reviews(df):
|
| 40 |
+
# 리뷰 점수가 2 이하인 부정 리뷰 필터링
|
| 41 |
+
negative_reviews = df[df['ReviewScore'] <= 2].sort_values(by='Review Length', ascending=False)
|
| 42 |
+
negative_reviews = negative_reviews.head(30) # 상위 30개 리뷰 선택
|
| 43 |
+
|
| 44 |
+
negative_reviews.reset_index(drop=True, inplace=True)
|
| 45 |
+
negative_reviews.index += 1
|
| 46 |
+
negative_reviews['순번'] = negative_reviews.index
|
| 47 |
+
|
| 48 |
+
# 리뷰 형식 지정
|
| 49 |
+
negative_output = "\n\n".join(negative_reviews.apply(
|
| 50 |
+
lambda x: f"{x['순번']}. **{x['Review Date']} / {x['ID']} / {x['Option']}**\n\n{x['Review']}", axis=1))
|
| 51 |
+
return negative_output
|
| 52 |
+
|
| 53 |
+
# 리뷰 데이터를 처리하여 긍정 및 부정 리뷰를 추출하는 함수
|
| 54 |
+
def process_reviews(file):
|
| 55 |
+
df = read_excel_data(file)
|
| 56 |
+
positive_reviews = get_positive_reviews(df)
|
| 57 |
+
negative_reviews = get_negative_reviews(df)
|
| 58 |
+
return positive_reviews, negative_reviews
|
| 59 |
+
|
| 60 |
+
# Gradio 인터페이스 구성
|
| 61 |
+
def create_interface():
|
| 62 |
+
with gr.Blocks() as demo:
|
| 63 |
+
gr.Markdown("### 리뷰 데이터 업로드")
|
| 64 |
+
file_input = gr.File(label="엑셀 파일 업로드", file_types=[".xlsx"])
|
| 65 |
+
analyze_button = gr.Button("리뷰 추출하기")
|
| 66 |
+
|
| 67 |
+
with gr.Column():
|
| 68 |
+
gr.Markdown("### 긍정적인 주요 리뷰 (최대 20개)")
|
| 69 |
+
positive_reviews_output = gr.Textbox(label="긍정적인 주요 리뷰", interactive=False, lines=20)
|
| 70 |
+
|
| 71 |
+
gr.Markdown("### 부정적인 주요 리뷰 (최대 30개)")
|
| 72 |
+
negative_reviews_output = gr.Textbox(label="부정적인 주요 리뷰", interactive=False, lines=30)
|
| 73 |
+
|
| 74 |
+
analyze_button.click(
|
| 75 |
+
fn=process_reviews,
|
| 76 |
+
inputs=[file_input],
|
| 77 |
+
outputs=[positive_reviews_output, negative_reviews_output]
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
return demo
|
| 81 |
+
|
| 82 |
+
if __name__ == "__main__":
|
| 83 |
+
interface = create_interface()
|
| 84 |
+
interface.launch()
|