| | |
| | """ |
| | gradio_app.py의 process_text 함수를 위한 래퍼 |
| | 새로운 3단계 Phase 파이프라인을 사용하여 기존 인터페이스와 호환 |
| | """ |
| |
|
| | from __future__ import annotations |
| | from typing import Tuple, Optional |
| | from .coconut_pipeline import run_full_analysis |
| | from .models import UtteranceAnalysisRequest |
| |
|
| |
|
| | def process_text_with_pipeline( |
| | text: str, |
| | context_situation: str, |
| | situation: str = "기타", |
| | profile_id: Optional[int] = None, |
| | analysis_mode: str = "detailed" |
| | ) -> Tuple[bool, str, str, str, str, str, str]: |
| | """ |
| | 새로운 3단계 Phase 파이프라인을 사용하여 텍스트 분석 |
| | |
| | Returns: |
| | (is_echo, confidence_html, quick_summary_text, three_step_text, detailed_report, save_message, analysis_id) |
| | analysis_id는 Optional[int]이지만 Tuple에서는 None을 반환 |
| | """ |
| | |
| | user_id = str(profile_id) if profile_id else "anonymous" |
| | |
| | |
| | dialogue_log = [ |
| | {"speaker": "caregiver", "utterance": context_situation or "상황 설명 없음"}, |
| | {"speaker": "child", "utterance": text} |
| | ] |
| | |
| | req = UtteranceAnalysisRequest( |
| | user_id=user_id, |
| | context_description=context_situation or situation, |
| | dialogue_log=dialogue_log, |
| | ) |
| | |
| | |
| | try: |
| | result = run_full_analysis(req) |
| | |
| | |
| | is_echo = result.echolalia_detection.is_echolalia |
| | |
| | |
| | |
| | if is_echo: |
| | |
| | |
| | type_weight = { |
| | 'immediate': 0.9, |
| | 'delayed': 0.7, |
| | 'mixed': 0.6, |
| | 'uncertain': 0.4 |
| | } |
| | completeness_weight = { |
| | 'full': 1.0, |
| | 'partial': 0.7, |
| | 'transformed': 0.5 |
| | } |
| | |
| | |
| | base_confidence = type_weight.get(result.echolalia_detection.type, 0.5) |
| | |
| | |
| | completeness_mult = completeness_weight.get(result.echolalia_detection.completeness, 0.7) |
| | |
| | |
| | functional_bonus = 0.1 if result.echolalia_detection.functional else 0.0 |
| | |
| | |
| | confidence = min(0.9, max(0.3, base_confidence * completeness_mult + functional_bonus)) |
| | else: |
| | |
| | confidence = 0.2 |
| | |
| | |
| | confidence_html = _generate_confidence_html(is_echo, confidence * 100) |
| | quick_summary_text = _generate_quick_summary(result, text) |
| | three_step_text = "" |
| | detailed_report = _generate_detailed_report( |
| | result, analysis_mode, text, context_situation, situation, profile_id, None |
| | ) |
| | save_message = "분석 결과가 프로필에 저장되었습니다." if profile_id else "프로필을 선택하면 분석 결과가 자동으로 저장됩니다." |
| | analysis_id = None |
| | |
| | return (is_echo, confidence_html, quick_summary_text, three_step_text, detailed_report, save_message, analysis_id) |
| | |
| | except Exception as e: |
| | |
| | import traceback |
| | error_trace = traceback.format_exc() |
| | print(f"❌ process_text_with_pipeline 에러: {e}") |
| | print(f"에러 상세:\n{error_trace}") |
| | error_html = f"<div style='background: #fee; border: 2px solid #f44; border-radius: 8px; padding: 20px; margin: 15px 0; text-align: center;'><h3>❌ 분석 오류</h3><p>{str(e)}</p></div>" |
| | return (False, error_html, "", "", "", f"분석 중 오류가 발생했습니다: {str(e)}", None) |
| |
|
| |
|
| | def _generate_confidence_html(is_echo: bool, confidence: float) -> str: |
| | """신뢰도 HTML 생성""" |
| | if confidence >= 70: |
| | color = "#ef4444" |
| | bg_color = "#fee2e2" |
| | icon = "⚠️" |
| | urgency = "관찰 필요" |
| | elif confidence >= 40: |
| | color = "#f59e0b" |
| | bg_color = "#fef3c7" |
| | icon = "📊" |
| | urgency = "지속 관찰" |
| | else: |
| | color = "#10b981" |
| | bg_color = "#d1fae5" |
| | icon = "✅" |
| | urgency = "양호" |
| | |
| | return f""" |
| | <div style='background: {bg_color}; border: 2px solid {color}; border-radius: 12px; padding: 20px; margin: 15px 0; text-align: center;'> |
| | <div style='font-size: 48px; margin-bottom: 10px;'>{icon}</div> |
| | <h2 style='color: {color}; margin: 5px 0;'>{confidence:.0f}%</h2> |
| | <p style='color: {color}; font-size: 1.2rem; margin: 5px 0;'><strong>{urgency}</strong></p> |
| | </div> |
| | """ |
| |
|
| |
|
| | def _generate_quick_summary(result, text: str) -> str: |
| | """빠른 요약 생성""" |
| | is_echo = result.echolalia_detection.is_echolalia |
| | primary_interpretation = result.meaning_inference.primary_interpretation |
| | |
| | if is_echo: |
| | return f""" |
| | ### ⚠️ 분석 결과 요약 |
| | |
| | **아이의 말**: "{text}" |
| | |
| | {primary_interpretation} |
| | """ |
| | else: |
| | return f""" |
| | ### ✅ 분석 결과 요약 |
| | |
| | **아이의 말**: "{text}" |
| | |
| | 정상적인 의사소통 패턴으로 보입니다. 🎉 |
| | """ |
| |
|
| |
|
| |
|
| |
|
| | def _translate_echolalia_tag(tag: str) -> str: |
| | """반향어 기능 태그를 한국어로 변환""" |
| | tag_map = { |
| | "FILLING_TURN": "대화 차례 채우기", |
| | "SAYING_YES": "동의 표현", |
| | "LABELING_PRACTICE": "명명 연습", |
| | "SELF_SOOTHING_ROUTINE": "자기 진정 루틴", |
| | "STIMMING_VERBAL": "구어적 자극 행동", |
| | "SOUND_PLEASURE": "소리 즐기기", |
| | "LANGUAGE_PROCESSING_OUTLOUD": "언어 처리 발화", |
| | "SITUATION_SCRIPT_REPLAY": "상황 스크립트 재현", |
| | "COMMUNICATION_ATTEMPT": "의사소통 시도", |
| | "ANXIETY_DEFENSE": "불안 방어", |
| | } |
| | return tag_map.get(tag, tag) |
| |
|
| |
|
| | def _translate_relative_level(level: str) -> str: |
| | """발달 수준을 한국어로 변환""" |
| | level_map = { |
| | "strength": "강점 영역", |
| | "age_appropriate": "또래 수준", |
| | "age_appropriate_or_mild_delay": "또래 수준 (약간의 지연 가능)", |
| | "developing": "발달 진행 중", |
| | "emerging": "발달 시작 단계", |
| | "needs_more_observation": "추가 관찰 필요", |
| | } |
| | return level_map.get(level, level) |
| |
|
| |
|
| | def _generate_detailed_report(result, analysis_mode: str, text: str = "", context_situation: str = "", |
| | situation: str = "기타", profile_id: int = None, analysis_id: int = None) -> str: |
| | """ |
| | 상세 보고서 생성 - 새로운 파이프라인 결과만 사용하여 "아이의 말에 담긴 마음" 형식으로 생성 |
| | """ |
| | if analysis_mode == "quick": |
| | return "" |
| | |
| | |
| | is_echo = result.echolalia_detection.is_echolalia |
| | |
| | |
| | profile_info = "" |
| | if result.development_profile.age_reference: |
| | age_years = result.development_profile.age_reference // 12 |
| | age_months = result.development_profile.age_reference % 12 |
| | profile_info = f""" |
| | **👶 기본 정보** |
| | - **나이**: {age_years}세 {age_months}개월 |
| | - **반향어 경향**: {'높은 경향' if is_echo else '낮은 경향'} ({result.echolalia_detection.type or '미확인'}) |
| | """ |
| | |
| | |
| | echo_type_kr = { |
| | 'immediate': '즉시 반향어', |
| | 'delayed': '지연 반향어', |
| | 'mixed': '혼합형', |
| | 'uncertain': '불확실' |
| | }.get(result.echolalia_detection.type, '미확인') |
| | |
| | primary_function = "" |
| | if result.meaning_inference.echolalia_functions: |
| | top_function = result.meaning_inference.echolalia_functions[0] |
| | function_tag_kr = _translate_echolalia_tag(top_function.tag) |
| | primary_function = f""" |
| | **🧠 언어 지도 (Language Map)** |
| | 아이는 **{echo_type_kr}**를 주로 사용하며, |
| | 반복 언어를 통해 **{function_tag_kr}** 기능을 하고 있습니다. |
| | |
| | {top_function.caregiver_explanation} |
| | |
| | **💡 언어 특성 이해** |
| | - **사회적 상호작용**: {echo_type_kr}를 통한 의사소통 시도 |
| | - **언어적 유연성**: 반복을 통한 안정감 추구 |
| | - **감정 표현**: 반복 언어를 통한 내적 상태 전달 |
| | """ |
| | |
| | personal_profile = f""" |
| | ### 1️⃣ 아이의 언어 성향 분석 (Personal Profile) |
| | {profile_info} |
| | {primary_function} |
| | """ |
| | |
| | |
| | context_interpretation = "" |
| | if result.echolalia_detection.evidence: |
| | if result.echolalia_detection.functional: |
| | context_interpretation = "**상황과 잘 맞는 발화**입니다. 아이가 현재 상황을 이해하고 적절하게 반응하고 있습니다." |
| | else: |
| | context_interpretation = "**부분적으로 상황과 연관된 발화**입니다. 아이가 상황의 일부를 이해하고 있지만 완전한 연결은 어려워 보입니다." |
| | else: |
| | context_interpretation = "**상황과 무관한 발화**일 가능성이 높습니다. 아이가 이전에 들은 말을 현재 상황과 연결하지 못하고 있습니다." |
| | |
| | function_type = "**의미 전달**" if result.echolalia_detection.functional else "**단순 모방**" |
| | function_desc = "아이가 명확한 의미를 전달하려고 시도하고 있습니다." if result.echolalia_detection.functional else "아이가 이전에 들은 말을 그대로 반복하고 있습니다." |
| | |
| | context_function_analysis = f""" |
| | ### 2️⃣ 입력 발화 및 대화 분석 (Context & Function) |
| | |
| | **🗣️ 발화 내용**: "{text}" |
| | |
| | **📍 맥락 분석** |
| | - **상황**: {situation} |
| | - **상황 설명**: {context_situation if context_situation else '제공되지 않음'} |
| | |
| | {context_interpretation} |
| | |
| | **🔍 기능 분석** |
| | - **발화 유형**: {function_type} |
| | - **설명**: {function_desc} |
| | |
| | **💭 구체적 해석** |
| | {result.meaning_inference.primary_interpretation} |
| | |
| | **반향어 기능 분석**: |
| | """ |
| | for func in result.meaning_inference.echolalia_functions: |
| | function_tag_kr = _translate_echolalia_tag(func.tag) |
| | context_function_analysis += f"- **{function_tag_kr}** (신뢰도: {func.confidence:.1%}): {func.caregiver_explanation}\n" |
| | |
| | |
| | caregiver_response = f""" |
| | **🧡 보호자 반응 방식** |
| | |
| | ✅ **해야 할 것** |
| | """ |
| | for response in result.parent_guide.immediate_response: |
| | caregiver_response += f"- {response}\n" |
| | |
| | caregiver_response += f""" |
| | **💬 아이를 위한 대안 발화 모델링** |
| | """ |
| | for utterance in result.parent_guide.modeling_utterance: |
| | caregiver_response += f"- {utterance}\n" |
| | |
| | caregiver_response += f""" |
| | **🎯 장기 지원 팁** |
| | """ |
| | for tip in result.parent_guide.long_term_tips: |
| | caregiver_response += f"- {tip}\n" |
| | |
| | alternative_strategy = f""" |
| | ### 3️⃣ 보완 방향 (Alternative & Strategy) |
| | |
| | {caregiver_response} |
| | |
| | **📚 발달 영역별 평가 및 지원 방향** |
| | """ |
| | for domain, domain_profile in result.development_profile.domains.items(): |
| | domain_name_kr = { |
| | 'pragmatics': '화용론', |
| | 'semantics': '의미론', |
| | 'morphosyntax': '형태통사론', |
| | 'communicative_function': '의사소통 기능' |
| | }.get(domain, domain) |
| | |
| | level_kr = _translate_relative_level(domain_profile.relative_level) |
| | |
| | alternative_strategy += f""" |
| | **{domain_name_kr}** |
| | - **수준**: {level_kr} |
| | - **요약**: {domain_profile.summary} |
| | - **참고사항**: {domain_profile.notes or '없음'} |
| | """ |
| | |
| | if result.development_profile.safety_note: |
| | alternative_strategy += f"\n**안전 참고사항**: {result.development_profile.safety_note}\n" |
| | |
| | |
| | report = f"""## 🌟 아이의 말에 담긴 마음 - 3단계 분석 보고서 |
| | |
| | **📌 참고사항**: 이 보고서는 coconut AI가 의학 자문을 통해 검증한 고유 데이터베이스를 기반으로 생성되었습니다. |
| | |
| | {personal_profile} |
| | |
| | {context_function_analysis} |
| | |
| | {alternative_strategy} |
| | |
| | --- |
| | *이 보고서는 공감적 접근을 바탕으로 한 AI 분석 시스템을 통해 생성되었습니다. 정확한 진단을 위해서는 전문가와의 상담을 권장합니다.*""" |
| | |
| | return report |
| |
|
| |
|