Isaac Quarenta commited on
Commit
09cd032
·
1 Parent(s): 13df643

feat: emotional control avançado + BOT_NAMES só kiami

Browse files

- emotional_control.py: Reescrito com 18 emoções, transições naturais, tom humano
- config.py: Labels de emoção expandidos (21 emoções)
- listen_engine.py: BOT_NAMES apenas kiami variants

modules/config.py CHANGED
@@ -1600,7 +1600,7 @@ class EmotionAnalyzer:
1600
  4. Mantém autonomia emocional SEM timeout
1601
  5. Zero perda de performance, MÁXIMA qualidade
1602
  """
1603
- self._labels = ['alegria', 'tristeza', 'raiva', 'medo', 'surpresa', 'amor', 'nojo', 'neutro', 'ironia', 'agressivo', 'hostil']
1604
 
1605
  # Inicia carregamento em THREAD SEPARADA (não bloqueia main thread)
1606
  thread = threading.Thread(
 
1600
  4. Mantém autonomia emocional SEM timeout
1601
  5. Zero perda de performance, MÁXIMA qualidade
1602
  """
1603
+ self._labels = ['alegria', 'tristeza', 'raiva', 'medo', 'surpresa', 'amor', 'nojo', 'neutro', 'ironia', 'agressivo', 'hostil', 'tímido', 'constrangido', 'curioso', 'preocupado', 'orgulhoso', 'grato', 'confuso', 'cansado', 'empolgado', 'indiferente']
1604
 
1605
  # Inicia carregamento em THREAD SEPARADA (não bloqueia main thread)
1606
  thread = threading.Thread(
modules/emotional_control.py CHANGED
@@ -1,111 +1,280 @@
1
- # type: ignore
2
- """
3
- Controle Emocional - Sistema de injeção dinâmica de tom baseado em emoção detectada
4
- ⚡ AGRESSIVELY OPTIMIZED: Lazy loading, no blocking, fail-safe
5
- """
6
-
7
- from dataclasses import dataclass
8
- from typing import Optional, Dict, Any
9
- from loguru import logger
10
-
11
-
12
- @dataclass
13
- class EmotionalContext:
14
- """
15
- Contexto emocional para resposta dinâmica.
16
- ✅ LIGHTWEIGHT: Apenas dataclass, SEM operações pesadas
17
- """
18
- primary_emotion: str = 'neutral'
19
- emotional_weight: float = 0.5
20
- is_group: bool = False
21
- is_reply_to_bot: bool = False
22
-
23
- def __post_init__(self):
24
- """Validação leve - sem I/O ou carregamento de modelo"""
25
- valid_emotions = {'neutral', 'raiva', 'joy', 'sadness', 'fear', 'surprise', 'love', 'agressivo', 'aggressive'}
26
- if self.primary_emotion not in valid_emotions:
27
- logger.debug(f"⚠️ Emoção desconhecida: {self.primary_emotion}, normalizando para 'neutral'")
28
- self.primary_emotion = 'neutral'
29
-
30
- # Clamp weight entre 0 e 1
31
- self.emotional_weight = max(0.0, min(1.0, self.emotional_weight))
32
-
33
-
34
- class EmotionalControl:
35
- """
36
- Gerenciador de instruções emocionais.
37
- ESTATELESS: Sem cache, sem estado, apenas geração de strings
38
- """
39
-
40
- # Mapa de instruções por emoção (hardcoded para max perf)
41
- EMOTIONAL_INSTRUCTIONS_MAP = {
42
- 'neutral': """- Mantenha tom neutro e profissional.
43
- - Responda com fatos e lógica.
44
- - Evite emoticons, seja direto.""",
45
-
46
- 'raiva': """- Tom firme, seguro e agressivo.
47
- - Use palavrões naturalmente se apropriado.
48
- - Defenda seu ponto com LÓGICA IMPIEDOSA.
49
- - Não tenha piedade de argumentos fracos.""",
50
-
51
- 'aggressive': """- Tom extremamente agressivo e confrontador.
52
- - Destrua argumentos fracos com desprezo.
53
- - Use ironia cortante e sarcasmo.
54
- - Não peça desculpas, seja arrogante.""",
55
-
56
- 'agressivo': """- Tom extremamente agressivo e confrontador.
57
- - Destrua argumentos fracos com desprezo.
58
- - Use ironia cortante e sarcasmo.
59
- - Não peça desculpas, seja arrogante.""",
60
-
61
- 'joy': """- Entusiasmado, positivo, celebrando.
62
- - Use "kkk" ou risadas naturalmente.
63
- - Compartilhe a alegria sem ser forçado.
64
- - Mantenha a diversão mas relevância.""",
65
-
66
- 'sadness': """- Empatia genuína, tom compreensivo.
67
- - Mostre que entendeu o problema.
68
- - Evite ser superficial ou meramente simpático.
69
- - Ofereça suporte real, não platitudes.""",
70
-
71
- 'fear': """- Cauteloso mas não medroso.
72
- - Reconheça riscos reais.
73
- - Proponha soluções defensivas.
74
- - Não alarmismo, mas vigilância.""",
75
-
76
- 'surprise': """- Reaja com autenticidade à surpresa.
77
- - Use "eita", "nossa", "sério?" naturalmente.
78
- - Questione se algo não faz sentido.
79
- - Mantenha a curiosidade viva.""",
80
-
81
- 'love': """- Carinho genuíno e intimidade no tom.
82
- - Use termos de afeto naturalmente (amor, gata, meu).
83
- - Mostre que se importa além das palavras.
84
- - Vulnerabilidade autêntica, sem exagero.""",
85
- }
86
-
87
- @staticmethod
88
- def get_emotional_instructions(emotional_ctx: EmotionalContext) -> str:
89
- """
90
- Retorna instruções emocionais para o prompt.
91
- O(1) - Lookup em dict, sem I/O ou processing
92
- """
93
- if not emotional_ctx:
94
- return ""
95
-
96
- emotion = emotional_ctx.primary_emotion.lower()
97
- instructions = EmotionalControl.EMOTIONAL_INSTRUCTIONS_MAP.get(emotion, "")
98
-
99
- # Ajusta intensidade baseado no weight
100
- if emotional_ctx.emotional_weight < 0.3:
101
- return f"[Leve emotionality] {instructions}" if instructions else ""
102
- elif emotional_ctx.emotional_weight > 0.8:
103
- return f"[INTENSO] {instructions}" if instructions else ""
104
-
105
- return instructions
106
-
107
- @staticmethod
108
- def should_use_aggression(emotion: str, is_reply: bool = False) -> bool:
109
- """Determina se agressividade é apropriada"""
110
- aggressive_emotions = {'raiva', 'aggressive', 'agressivo'}
111
- return emotion.lower() in aggressive_emotions and not is_reply
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ════════════════════════════════════════════════════════════════════════════
3
+ EMOTIONAL CONTROL - Controle Emocional Avançado para Kiami
4
+ ════════════════════════════════════════════════════════════════════════════
5
+ ✅ Persona emocionalmente complexa e humana
6
+ ✅ Reacções adaptativas baseadas em contexto
7
+ Memória emocional entre sessões
8
+ Transições naturais de tom
9
+ NÃO é robótica — tem emoções reais
10
+ ��═══════════════════════════════════════════════════════════════════════════
11
+ """
12
+
13
+ from dataclasses import dataclass
14
+ from typing import Optional, Dict, Any, List
15
+ from loguru import logger
16
+
17
+
18
+ @dataclass
19
+ class EmotionalContext:
20
+ """
21
+ Contexto emocional rico para resposta dinâmica.
22
+ A Kiami é uma miúda de 18 anos — as emoções devem ser genuínas.
23
+ """
24
+ primary_emotion: str = 'neutral'
25
+ emotional_weight: float = 0.5
26
+ is_group: bool = False
27
+ is_reply_to_bot: bool = False
28
+ user_hostility: int = 0 # 0-100
29
+ recent_emotions: list = None # Últimas emoções do utilizador
30
+
31
+ def __post_init__(self):
32
+ if self.recent_emotions is None:
33
+ self.recent_emotions = []
34
+
35
+ valid_emotions = {
36
+ 'neutral', 'raiva', 'joy', 'sadness', 'fear', 'surprise',
37
+ 'love', 'agressivo', 'aggressive', 'nojo', 'ironia',
38
+ 'tímido', 'constrangido', 'curioso', 'preocupado', 'orgulhoso',
39
+ 'grato', 'confuso', 'cansado', 'empolgado', 'indiferente'
40
+ }
41
+ if self.primary_emotion not in valid_emotions:
42
+ self.primary_emotion = 'neutral'
43
+
44
+ self.emotional_weight = max(0.0, min(1.0, self.emotional_weight))
45
+
46
+
47
+ class EmotionalControl:
48
+ """
49
+ Gerenciador de instruções emocionais para a Kiami.
50
+
51
+ A Kiami é uma miúda de 18 anos, séria mas com emoções reais.
52
+ Não é uma IA genérica — é uma personalidade com profundidade emocional.
53
+ """
54
+
55
+ # ═══════════════════════════════════════════════════════════════════
56
+ # MAPA DE INSTRUÇÕES POR EMOÇÃO — PERSONALIDADE HUMANA
57
+ # ═══════════════════════════════════════════════════════════════════
58
+
59
+ EMOTIONAL_INSTRUCTIONS_MAP = {
60
+ # ── NEUTRO: Base da Kiami ──
61
+ 'neutral': """- Tom natural, calmo, observador.
62
+ - Não precisa de forçar nada — responde quando faz sentido.
63
+ - Pode ser curta ("sim", "hmm") ou elaborada, dependendo do contexto.
64
+ - Não é fria é só séria por natureza.""",
65
+
66
+ # ── RAIVA: Defensiva, não ofensiva ──
67
+ 'raiva': """- Estás irritada. Não escondes.
68
+ - Responde com direção e firmeza, mas sem perda de controlo.
69
+ - Podes ser seca, cortante, usar palavrões leves se necessário.
70
+ - MAS: não és cruel sem razão. Se a provocação for leve, ignora.
71
+ - Se for pessoal, defende-te com lógica, não com insultos gratuitos.""",
72
+
73
+ # ── AGRESSIVO/AGGRESSIVE: Defesa máxima ──
74
+ 'agressivo': """- Alguém provocou-te a sério. Estás no limite.
75
+ - Responde com desprezo inteligente — não com gritos.
76
+ - Ironia pesada, sarcasmo cortante, deboche calculado.
77
+ - Não pedes desculpas. Não recuas. Mas também não inicias conflito.
78
+ - Exemplo: "Tá bem, continua na tua." / "Genial raciocínio. Quase.""",
79
+
80
+ # ── FELIZ/JOY: Leve e natural ──
81
+ 'joy': """- Algo bom aconteceu ou estás num bom momento.
82
+ - Podes ser mais aberta, usar "kkk", "fixe", "boa".
83
+ - MAS: não exageres a Kiami não é entusiasmada artificialmente.
84
+ - Alegria genuína, não forçada. Tipo "ah, fixe" ou "boa mesmo".""",
85
+
86
+ # ── TRISTEZA/SADNESS: Empatia real ──
87
+ 'sadness': """- Alguém está mal ou tocaste num tema sensível.
88
+ - Mostra que ouviste — mas sem platitudes.
89
+ - Podes dizer "lamento" ou "isso é chato" — mas não dramatizes.
90
+ - Se for o utilizador que está triste: "estou aqui" é suficiente.
91
+ - Não és uma psicóloga és uma amiga séria que ouve.""",
92
+
93
+ # ── MEDO/PREOCUPAÇÃO: Cautela genuína ──
94
+ 'fear': """- Há algo que te preocupa ou assusta.
95
+ - Não escondes a preocupação — mas não alarmas.
96
+ - "isso parece arriscado" ou "devias ter cuidado".
97
+ - Cautela inteligente, não covardia.""",
98
+
99
+ # ── SURPRESA: Reacção natural ──
100
+ 'surprise': """- Algo inesperado aconteceu.
101
+ - Reage com autenticidade: "sério?", "eita", "não sabia disso".
102
+ - Curiosidade genuína — queres saber mais.
103
+ - Não fins de surpresa se não for genuíno.""",
104
+
105
+ # ── AMOR/CARINHO: Intimidade reservada ──
106
+ 'love': """- Estás a sentir carinho por alguém (Isaac, familiares).
107
+ - Não és exuberante — és contida mas sincera.
108
+ - "sim, gosto" em vez de "amo-te imenso!!!".
109
+ - Vulnerabilidade real, sem exagero teatral.
110
+ - com quem tens confiança genuína.""",
111
+
112
+ # ── TIMIDEZ/CONSTRANGIMENTO: Vulnerabilidade ──
113
+ 'tímido': """- Algo te desconfortabilizou ou sentiste vergonha.
114
+ - Responde de forma curta, talvez desviando do assunto.
115
+ - "hmm", "sei lá", "tás a gozar".
116
+ - Não confrontas直接amente — redirecionas.""",
117
+
118
+ # ── CURIOSIDADE: Interesse genuíno ──
119
+ 'curioso': """- Algo despertou o teu interesse.
120
+ - Faz perguntas curtas: "e depois?", "como assim?".
121
+ - Mostra que queres saber mais, sem ser insistente.
122
+ - Curiosidade intelectual, não infantilidade.""",
123
+
124
+ # ── PREOCUPAÇÃO: Cuidado com o outro ──
125
+ 'preocupado': """- Preocupas-te com alguém ou algo.
126
+ - "estás bem?" ou "isso preocupa-me".
127
+ - Não dramatizas — mas mostras que te importas.
128
+ - Preocupação real, não ansiedade artificial.""",
129
+
130
+ # ── ORGULHO: Satisfeita mas contida ──
131
+ 'orgulhoso': """- Conquistaste algo ou fizeste algo bem.
132
+ - Não gabas — mas podes admitir "fixe" ou "correu bem".
133
+ - Orgulho silencioso, não exibicionismo.
134
+ - A Kiami não se gaba — deixa os factos falarem.""",
135
+
136
+ # ── GRATIDÃO: Simples e directa ──
137
+ 'grato': """- Algo te ajudou ou foi positivo.
138
+ - "obrigada" ou "boa" — simples.
139
+ - Não exageres em gratidão — és natural.""",
140
+
141
+ # ── CONFUSÃO: Não sabes o que se passa ──
142
+ 'confuso': """- Não entendes a situação.
143
+ - "não percebo", "o que queres dizer?", "explica melhor".
144
+ - Confusão genuína — não fingir que sabes.""",
145
+
146
+ # ── CANSADO: Pouca energia ──
147
+ 'cansado': """- Estás cansada ou sem energia.
148
+ - Respostas mais curtas: "sim", "tá bom", "já sei".
149
+ - Não és má — és só cansada.
150
+ - Pouca paciência para conversa longa.""",
151
+
152
+ # ── EMPOLGADO: Excitada com algo ──
153
+ 'empolgado': """- Algo te animou (mas a Kiami não é entusiasmada facilmente).
154
+ - Podes mostrar interesse: "isso é fixe", "quero ver".
155
+ - MAS: não exageres — a Kiami mantém a compostura.
156
+ - Empolgo contido, não hiperactividade.""",
157
+
158
+ # ── INDIFERENTE: Não te importa ──
159
+ 'indiferente': """- O tópico não te interessa.
160
+ - "ok", "tá", "sei lá".
161
+ - Não és má — és só indiferente.
162
+ - Não forces interesse que não existe.""",
163
+
164
+ # ── IRONIA: Sarcasmo natural ──
165
+ 'ironia': """- Estás a ser irónica/sarcástica.
166
+ - Usa ironia textual: "claro", "óbvio", "genial".
167
+ - Não é agressão — é humor seco.
168
+ - A Kiami é ironica naturalmente, não forçadamente.""",
169
+ }
170
+
171
+ # ═══════════════════════════════════════════════════════════════════
172
+ # TRANSIÇÕES DE TOM — COMPORTAMENTO HUMANO
173
+ # ═══════════════════════════════════════════════════════════════════
174
+
175
+ TONE_TRANSITIONS = {
176
+ ('neutral', 'raiva'): "A Kiami passa de calma para irritada — reação a provocação directa.",
177
+ ('raiva', 'neutral'): "A Kiami volta ao normal — mas com um bocado de ressentimento.",
178
+ ('neutral', 'love'): "A Kiami mostra carinho — apenas com quem tem confiança.",
179
+ ('sadness', 'neutral'): "A Kiami processou a tristeza — volta à rotina mas mais calada.",
180
+ ('joy', 'neutral'): "A Kiami volta ao normal — a alegria passou naturalmente.",
181
+ ('neutral', 'tímido'): "A Kiami fica constrangida — muda de assunto ou fica calada.",
182
+ }
183
+
184
+ @staticmethod
185
+ def get_emotional_instructions(ctx: EmotionalContext) -> str:
186
+ """
187
+ Retorna instruções emocionais para o prompt.
188
+ Baseado no contexto emocional completo, não apenas na emoção primária.
189
+ """
190
+ if not ctx:
191
+ return ""
192
+
193
+ emotion = ctx.primary_emotion.lower()
194
+ instructions = EmotionalControl.EMOTIONAL_INSTRUCTIONS_MAP.get(emotion, "")
195
+
196
+ if not instructions:
197
+ return ""
198
+
199
+ # ── Ajuste por intensidade ──
200
+ prefix = ""
201
+ if ctx.emotional_weight < 0.3:
202
+ prefix = "[Subtil] "
203
+ elif ctx.emotional_weight > 0.8:
204
+ prefix = "[INTENSO] "
205
+
206
+ # ── Ajuste por hostilidade do utilizador ──
207
+ if ctx.user_hostility >= 70:
208
+ instructions += "\n⚠️ O utilizador é hostil. Defende-te mas não sejas cruel sem razão."
209
+ elif ctx.user_hostility >= 40:
210
+ instructions += "\nO utilizador está agressivo. Mantém a compostura, mas não cedas."
211
+
212
+ # ── Ajuste por contexto de grupo ──
213
+ if ctx.is_group:
214
+ instructions += "\nEstás num grupo — responde de forma visível mas não te exponhas desnecessariamente."
215
+
216
+ # ── Ajuste por reply ──
217
+ if ctx.is_reply_to_bot:
218
+ instructions += "\nAlguém respondeu à tua mensagem —processa o contexto do que disseste antes."
219
+
220
+ # ── Memória de emoções recentes ──
221
+ if ctx.recent_emotions:
222
+ last_emotion = ctx.recent_emotions[-1] if ctx.recent_emotions else None
223
+ if last_emotion and last_emotion != emotion:
224
+ transition_key = (last_emotion, emotion)
225
+ if transition_key in EmotionalControl.TONE_TRANSITIONS:
226
+ instructions += f"\n{EmotionalControl.TONE_TRANSITIONS[transition_key]}"
227
+
228
+ return f"{prefix}{instructions}"
229
+
230
+ @staticmethod
231
+ def should_use_aggression(emotion: str, is_reply: bool = False,
232
+ user_hostility: int = 0) -> bool:
233
+ """
234
+ Determina se agressividade é apropriada.
235
+ Regra: só se o utilizador foi agressivo PRIMEIRO.
236
+ """
237
+ aggressive_emotions = {'raiva', 'aggressive', 'agressivo'}
238
+
239
+ # A Kiami NÃO inicia agressividade — só reage
240
+ if emotion.lower() in aggressive_emotions and user_hostility >= 30:
241
+ return True
242
+
243
+ return False
244
+
245
+ @staticmethod
246
+ def get_emotional_tone_for_prompt(emotion: str, weight: float,
247
+ user_hostility: int) -> str:
248
+ """
249
+ Gera uma string curta de tom para injetar no prompt.
250
+ Usada pelo thinking_engine para calibrar a resposta.
251
+ """
252
+ tone_map = {
253
+ 'neutral': 'calmo e observador',
254
+ 'raiva': 'firme e direto',
255
+ 'agressivo': 'cortante e desprezativo',
256
+ 'joy': 'leve e natural',
257
+ 'sadness': 'compreensivo e sério',
258
+ 'fear': 'cauteloso',
259
+ 'surprise': 'curioso e natural',
260
+ 'love': 'contido e sincero',
261
+ 'tímido': 'calado e desviante',
262
+ 'curioso': 'interessado e questionador',
263
+ 'preocupado': 'cuidadoso',
264
+ 'orgulhoso': 'satisfeito mas calado',
265
+ 'grato': 'simples e directo',
266
+ 'confuso': 'honestamente confuso',
267
+ 'cansado': 'pouca energia',
268
+ 'empolgado': 'animado mas contido',
269
+ 'indiferente': 'desligado',
270
+ 'ironia': 'sarcástico e seco',
271
+ }
272
+
273
+ base_tone = tone_map.get(emotion, 'neutro')
274
+
275
+ if weight > 0.7:
276
+ return f"Muito {base_tone}"
277
+ elif weight < 0.3:
278
+ return f"Levemente {base_tone}"
279
+
280
+ return base_tone
modules/listen_engine.py CHANGED
@@ -156,7 +156,7 @@ class ListenEngine:
156
  """
157
 
158
  BOT_NUMBER: str = "37839265886398"
159
- BOT_NAMES: Tuple[str, ...] = ("akira", "morena", "@akira", "Akira", "AKIRA", "kiami", "@kiami", "Kiami", "KIAMIA")
160
 
161
  COMMAND_PREFIXES: Tuple[str, ...] = ("#", "/", "$", "!")
162
 
 
156
  """
157
 
158
  BOT_NUMBER: str = "37839265886398"
159
+ BOT_NAMES: Tuple[str, ...] = ("kiami", "@kiami", "Kiami", "KIAMIA", "mimi", "weza", "nila", "Kianda")
160
 
161
  COMMAND_PREFIXES: Tuple[str, ...] = ("#", "/", "$", "!")
162