"""Heuristiska emocionālā konteksta noteikšana.""" from __future__ import annotations from dataclasses import dataclass KEYWORD_MATCH_SCORE = 0.22 TECHNICAL_CONTEXT_SCORE = 0.08 EXCLAMATION_BONUS = 0.08 QUESTION_BONUS = 0.04 MAX_PUNCTUATION_BONUS = 0.2 @dataclass(frozen=True, slots=True) class EmotionalContext: emotion: str confidence: float response_style: str guidance: str description: str _EMOTION_KEYWORDS: dict[str, tuple[str, ...]] = { "distressed": ( "palīdzi", "help me", "panic", "panika", "esmu nobijies", "bail", "anxiety", "trauksme", "overwhelmed", "nespēju", "hopeless", "izmisums", ), "frustrated": ( "nestrādā", "neiet", "salūza", "broken", "besī", "kaitina", "frustrated", "stuck", ), "urgent": ("steidzami", "urgent", "asap", "immediately", "tagad", "right now"), "excited": ( "super", "wow", "lieliski", "amazing", "awesome", "can't wait", "nevaru sagaidīt", "let's go", "fantastic", ), "curious": ( "kā", "why", "paskaidro", "explain", "pastāsti", "gribu saprast", "analyze", "izanalizē", "salīdzini", "compare", ), } _TECHNICAL_ISSUE_KEYWORDS = ("bug", "error", "kļūda", "issue", "problem", "problēma") _STYLE_GUIDANCE: dict[str, tuple[str, str]] = { "neutral": ( "clear_grounded", "Saglabā mierīgu, profesionālu un skaidru toni.", ), "curious": ( "exploratory_explanatory", "Esi izzinošs, strukturē atbildi un paskaidro domāšanas gaitu skaidri.", ), "excited": ( "energized_positive", "Atbildi ar pozitīvu enerģiju, bet saglabā saturu konkrētu un praktisku.", ), "frustrated": ( "calm_reassuring_step_by_step", "Atzīsti grūtību, nomierini toni un ved lietotāju pa skaidriem soļiem.", ), "distressed": ( "empathetic_supportive", "Atbildi empātiski, mierinoši un ar drošu, vienkāršu nākamo soli.", ), "urgent": ( "decisive_action_focused", "Īsi prioritizē, uzsver svarīgāko un dod tūlītēji izpildāmus nākamos soļus.", ), } _STYLE_DESCRIPTIONS: dict[str, str] = { "neutral": "mierīgs un līdzsvarots", "curious": "izzinošs un ieinteresēts", "excited": "pozitīvi uzlādēts", "frustrated": "saspringts un neapmierināts", "distressed": "noraizējies un pārņemts", "urgent": "steidzams un fokusēts", } def analyze_emotional_context(text: str) -> EmotionalContext: """Atgriež labāko emocionālo interpretāciju lietotāja tekstam.""" normalized = " ".join(text.lower().split()) if not normalized: return _context_for("neutral", 0.35) scores: dict[str, float] = {emotion: 0.0 for emotion in _STYLE_GUIDANCE} punctuation_bonus = min( text.count("!") * EXCLAMATION_BONUS + text.count("?") * QUESTION_BONUS, MAX_PUNCTUATION_BONUS, ) for emotion, keywords in _EMOTION_KEYWORDS.items(): for keyword in keywords: if keyword in normalized: scores[emotion] += KEYWORD_MATCH_SCORE if any(keyword in normalized for keyword in _TECHNICAL_ISSUE_KEYWORDS): scores["frustrated"] += TECHNICAL_CONTEXT_SCORE if "?" in text and scores["curious"] == 0: scores["curious"] += 0.16 if text.count("!") >= 2: scores["excited"] += 0.14 if any(token.isupper() and len(token) > 2 for token in text.split()): scores["urgent"] += 0.1 strongest_emotion = max( (emotion for emotion in scores if emotion != "neutral"), key=lambda emotion: scores[emotion], default="neutral", ) strongest_score = scores[strongest_emotion] if strongest_score <= 0: return _context_for("neutral", min(0.45 + punctuation_bonus, 0.55)) confidence = min(0.5 + strongest_score + punctuation_bonus, 0.93) return _context_for(strongest_emotion, confidence) def _context_for(emotion: str, confidence: float) -> EmotionalContext: response_style, guidance = _STYLE_GUIDANCE[emotion] return EmotionalContext( emotion=emotion, confidence=round(confidence, 2), response_style=response_style, guidance=guidance, description=_STYLE_DESCRIPTIONS[emotion], )