| """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], |
| ) |
|
|