π AI κ°μ λΆμκΈ°
νΈλμ€ν¬λ¨Έ κΈ°λ° λ€κ΅μ΄ κ°μ λΆμ λꡬ
""" π 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("""
νΈλμ€ν¬λ¨Έ κΈ°λ° λ€κ΅μ΄ κ°μ λΆμ λꡬ