File size: 4,569 Bytes
f440f03 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | """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],
)
|