DODOMOOVspace / app.py
DODOMOOV's picture
Rename code.py to app.py
5456b23 verified
"""
🎭 AI 감정 분석기
Hugging Face Spaces 배포용 완성 코드
"""
import gradio as gr
from transformers import pipeline
import logging
import os
# 로깅 설정
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 전역 변수로 모델 파이프라인 저장
sentiment_pipeline = None
def load_model():
"""모델 로딩 함수 - 앱 시작시 한번만 실행"""
global sentiment_pipeline
try:
logger.info("🤖 감정 분석 모델을 로딩 중...")
# 다국어 지원 모델 사용 (한국어 포함)
sentiment_pipeline = pipeline(
"sentiment-analysis",
model="nlptown/bert-base-multilingual-uncased-sentiment",
return_all_scores=False
)
logger.info("✅ 모델 로딩 완료!")
return True
except Exception as e:
logger.error(f"❌ 모델 로딩 실패: {str(e)}")
# 기본 모델로 fallback
try:
sentiment_pipeline = pipeline("sentiment-analysis")
logger.info("✅ 기본 모델로 로딩 완료!")
return True
except Exception as e2:
logger.error(f"❌ 기본 모델도 로딩 실패: {str(e2)}")
return False
def analyze_sentiment(text):
"""
감정 분석 메인 함수
Args:
text (str): 분석할 텍스트
Returns:
str: 분석 결과 (마크다운 형식)
"""
# 입력 검증
if not text or not text.strip():
return """
### ⚠️ 알림
텍스트를 입력해주세요! 😊
**사용법**: 아래 예시를 참고하거나 직접 문장을 입력해보세요.
"""
# 텍스트 길이 제한
if len(text) > 1000:
return """
### ❌ 오류
텍스트가 너무 깁니다. 1000자 이하로 입력해주세요.
"""
try:
logger.info(f"📝 분석 시작: {text[:50]}...")
# AI 모델로 감정 분석
result = sentiment_pipeline(text)[0]
# 결과 처리
label = result['label']
confidence = result['score']
logger.info(f"🎯 분석 결과: {label} ({confidence:.3f})")
# 라벨 매핑 (다국어 모델 지원)
emoji, korean_label, description = map_sentiment_label(label, confidence)
# 결과 포맷팅
result_markdown = f"""
### {emoji} 감정 분석 결과
**🎭 감정**: {korean_label}
**📊 확신도**: {confidence:.1%}
**🔍 상세**: {description}
---
**⚙️ 모델 정보**: {label} (원본)
**⏰ 분석 완료**: ✅
"""
return result_markdown
except Exception as e:
logger.error(f"💥 분석 중 오류: {str(e)}")
return f"""
### ❌ 분석 오류
죄송합니다. 분석 중 오류가 발생했습니다.
**오류 내용**: {str(e)}
**해결 방법**:
- 텍스트를 다시 확인해주세요
- 잠시 후 다시 시도해주세요
- 문제가 지속되면 새로고침 해주세요
"""
def map_sentiment_label(label, confidence):
"""
모델 라벨을 한국어로 매핑하고 설명 추가
Args:
label (str): 모델 출력 라벨
confidence (float): 신뢰도 점수
Returns:
tuple: (이모지, 한국어 라벨, 설명)
"""
label_str = str(label).upper()
# 긍정 감정 (POSITIVE, 4 STARS, 5 STARS)
if any(pos in label_str for pos in ['POSITIVE', '5', '4']):
if confidence > 0.8:
return "😍", "매우 긍정적", "아주 좋은 감정이 느껴집니다!"
else:
return "😊", "긍정적", "좋은 감정이 느껴집니다."
# 부정 감정 (NEGATIVE, 1 STAR, 2 STARS)
elif any(neg in label_str for neg in ['NEGATIVE', '1', '2']):
if confidence > 0.8:
return "😢", "매우 부정적", "강한 부정적 감정이 느껴집니다."
else:
return "😟", "부정적", "부정적 감정이 느껴집니다."
# 중립 감정 (3 STARS, NEUTRAL)
else:
return "😐", "중립적", "특별한 감정이 느껴지지 않습니다."
def create_interface():
"""Gradio 인터페이스 생성"""
# CSS 스타일링
custom_css = """
.gradio-container {
font-family: 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
max-width: 900px;
margin: 0 auto;
}
.main-header {
text-align: center;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
margin-bottom: 20px;
}
.footer-info {
text-align: center;
margin-top: 20px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 8px;
font-size: 14px;
color: #6c757d;
}
"""
# 인터페이스 생성
with gr.Blocks(
css=custom_css,
theme=gr.themes.Soft(
primary_hue="blue",
secondary_hue="purple",
neutral_hue="gray"
),
title="🎭 AI 감정 분석기"
) as demo:
# 헤더
gr.HTML("""
<div class="main-header">
<h1>🎭 AI 감정 분석기</h1>
<p>트랜스포머 기반 다국어 감정 분석 도구</p>
</div>
""")
# 메인 인터페이스
with gr.Row():
with gr.Column(scale=1):
text_input = gr.Textbox(
placeholder="감정을 분석할 텍스트를 입력하세요...\n예: '오늘 정말 좋은 하루였어요!'",
lines=4,
label="📝 텍스트 입력",
max_lines=8
)
analyze_btn = gr.Button(
"🔍 감정 분석하기",
variant="primary",
size="lg"
)
clear_btn = gr.Button(
"🗑️ 초기화",
variant="secondary"
)
with gr.Column(scale=1):
result_output = gr.Markdown(
value="""
### 👋 환영합니다!
왼쪽에 텍스트를 입력하고 **'감정 분석하기'** 버튼을 클릭하면
AI가 텍스트의 감정을 분석해드립니다.
**✨ 특징**:
- 🌍 다국어 지원 (한국어 최적화)
- 🎯 높은 정확도
- ⚡ 빠른 분석 속도
""",
label="🎯 분석 결과"
)
# 예시 데이터
gr.Markdown("### 📚 예시 문장들")
examples = gr.Examples(
examples=[
["오늘 정말 기분이 좋아요! 🌟"],
["이 영화는 정말 지루하고 재미없어요 😴"],
["그냥 평범한 하루였어요."],
["허깅페이스 워크숍 너무 재미있어요! 🚀"],
["AI 기술이 정말 신기하고 놀라워요 🤖"],
["이번 프로젝트는 완전 실패했어요... 😞"],
["새로운 도전이 기대되고 설레어요!"],
["날씨가 흐리고 우울해요"],
["친구들과 함께한 시간이 행복했어요"],
["시험 결과가 걱정돼요"]
],
inputs=text_input,
label="클릭하면 자동 입력됩니다"
)
# 이벤트 핸들러
analyze_btn.click(
fn=analyze_sentiment,
inputs=text_input,
outputs=result_output
)
clear_btn.click(
fn=lambda: ("", """
### 👋 환영합니다!
왼쪽에 텍스트를 입력하고 **'감정 분석하기'** 버튼을 클릭하면
AI가 텍스트의 감정을 분석해드립니다.
"""),
outputs=[text_input, result_output]
)
# Enter 키로도 분석 가능
text_input.submit(
fn=analyze_sentiment,
inputs=text_input,
outputs=result_output
)
# 푸터 정보
gr.HTML("""
<div class="footer-info">
<p>🤖 <strong>Powered by</strong>: Hugging Face Transformers + Gradio</p>
<p>📊 <strong>Model</strong>: BERT Multilingual Sentiment Analysis</p>
<p>💡 <strong>Tips</strong>: 한국어, 영어, 기타 언어 모두 지원합니다!</p>
</div>
""")
return demo
def main():
"""메인 실행 함수"""
print("🎭 AI 감정 분석기 시작!")
# 모델 로딩
if not load_model():
print("❌ 모델 로딩 실패! 앱을 시작할 수 없습니다.")
return
# 인터페이스 생성
demo = create_interface()
# 개발 환경 vs 배포 환경 설정
if os.getenv("SPACE_ID"): # Hugging Face Spaces에서 실행 중
print("🚀 Hugging Face Spaces에서 앱을 시작합니다...")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False # Spaces에서는 자동으로 공개됨
)
else: # 로컬에서 실행 중
print("💻 로컬 환경에서 앱을 시작합니다...")
demo.launch(
share=True, # 로컬에서는 공개 링크 생성
server_port=7860
)
if __name__ == "__main__":
main()