alive-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +24 -0
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/alive_ai/__init__.py +3 -0
- package/brain/__init__.py +59 -0
- package/brain/almost_said.py +154 -0
- package/brain/bid_detector.py +636 -0
- package/brain/conversation_flow.py +135 -0
- package/brain/curiosity.py +328 -0
- package/brain/default_mode.py +1438 -0
- package/brain/dreams.py +220 -0
- package/brain/embeddings/__init__.py +82 -0
- package/brain/emotional_memory.py +949 -0
- package/brain/global_activity.py +173 -0
- package/brain/group_dynamics.py +63 -0
- package/brain/linguistic.py +235 -0
- package/brain/llm/__init__.py +63 -0
- package/brain/llm/base.py +33 -0
- package/brain/llm/fallback_router.py +309 -0
- package/brain/llm/manifest.md +30 -0
- package/brain/llm/ollama.py +218 -0
- package/brain/llm/openrouter.py +151 -0
- package/brain/llm/provider.py +205 -0
- package/brain/llm/unified.py +423 -0
- package/brain/llm/zai.py +169 -0
- package/brain/manifest.md +23 -0
- package/brain/memory/__init__.py +123 -0
- package/brain/memory/episodic.py +92 -0
- package/brain/memory/fact_extractor.py +209 -0
- package/brain/memory/index.py +54 -0
- package/brain/memory/manager.py +151 -0
- package/brain/memory/summarizer.py +102 -0
- package/brain/memory/vector_store.py +297 -0
- package/brain/memory/working.py +43 -0
- package/brain/narrative.py +343 -0
- package/brain/stt/__init__.py +4 -0
- package/brain/stt/google_stt.py +83 -0
- package/brain/stt/whisper_stt.py +82 -0
- package/brain/subconscious/__init__.py +33 -0
- package/brain/subconscious/actions.py +136 -0
- package/brain/subconscious/evaluation.py +166 -0
- package/brain/subconscious/goal_system.py +90 -0
- package/brain/subconscious/goals.py +41 -0
- package/brain/subconscious/impulse_generator.py +200 -0
- package/brain/subconscious/impulses.py +48 -0
- package/brain/subconscious/learning.py +24 -0
- package/brain/subconscious/learning_system.py +79 -0
- package/brain/subconscious/loop.py +398 -0
- package/brain/subconscious/manifest.md +32 -0
- package/brain/subconscious/relationship.py +47 -0
- package/brain/subconscious/relationship_memory.py +83 -0
- package/brain/subconscious/response_analyzer.py +74 -0
- package/brain/subconscious/templates.py +70 -0
- package/brain/subconscious/thought.py +37 -0
- package/brain/subconscious/working_memory.py +97 -0
- package/cli/index.js +371 -0
- package/config/directives.example.json +28 -0
- package/config/instructions.example.md +16 -0
- package/config/self.example.json +74 -0
- package/config/settings.example.json +95 -0
- package/core/__init__.py +1 -0
- package/core/config.py +54 -0
- package/core/directives.py +198 -0
- package/core/events.py +50 -0
- package/core/follow_up.py +267 -0
- package/core/hot_reload.py +174 -0
- package/core/initialization.py +253 -0
- package/core/manifest.md +28 -0
- package/core/media_handler.py +241 -0
- package/core/memory_monitor.py +200 -0
- package/core/message_handler.py +1440 -0
- package/core/proactive_generator.py +277 -0
- package/core/self.py +188 -0
- package/core/settings.py +169 -0
- package/core/skills_registry.py +357 -0
- package/core/state.py +27 -0
- package/core/subconscious_bridge.py +93 -0
- package/core/thinking.py +175 -0
- package/core/user_manager.py +306 -0
- package/core/user_tracker.py +144 -0
- package/demo/index.html +144 -0
- package/docker-compose.yml +28 -0
- package/docs/assets/logo.svg +15 -0
- package/docs/index.html +355 -0
- package/heart/__init__.py +93 -0
- package/heart/afterglow.py +215 -0
- package/heart/attachment.py +186 -0
- package/heart/circadian.py +251 -0
- package/heart/complex_emotions.py +114 -0
- package/heart/conflicts.py +589 -0
- package/heart/core.py +387 -0
- package/heart/emotional_decay.py +59 -0
- package/heart/emotional_memory.py +261 -0
- package/heart/emotional_state.py +146 -0
- package/heart/emotional_variability.py +156 -0
- package/heart/hormonal.py +424 -0
- package/heart/inconsistency.py +1222 -0
- package/heart/integrity.py +469 -0
- package/heart/interoception.py +997 -0
- package/heart/love.py +120 -0
- package/heart/manifest.md +25 -0
- package/heart/mood_shifts.py +169 -0
- package/heart/phantom_somatic.py +259 -0
- package/heart/predictive.py +374 -0
- package/heart/scars.py +474 -0
- package/heart/somatic.py +482 -0
- package/heart/soul.py +633 -0
- package/heart/telemetry.py +942 -0
- package/heart/triggers.py +119 -0
- package/heart/unconscious.py +443 -0
- package/input/__init__.py +1 -0
- package/input/manifest.md +24 -0
- package/input/telegram/__init__.py +1 -0
- package/input/telegram/commands.py +762 -0
- package/input/telegram/listener.py +532 -0
- package/main.py +90 -0
- package/manifest.md +28 -0
- package/mypics/.gitkeep +1 -0
- package/myvids/.gitkeep +1 -0
- package/output/__init__.py +1 -0
- package/output/images/__init__.py +1 -0
- package/output/images/fal_gen.py +43 -0
- package/output/manifest.md +26 -0
- package/output/text/__init__.py +1 -0
- package/output/text/sender.py +22 -0
- package/output/voice/__init__.py +64 -0
- package/output/voice/google_tts.py +252 -0
- package/output/voice/gtts_tts.py +214 -0
- package/output/voice/vibe_tts.py +190 -0
- package/package.json +58 -0
- package/pyproject.toml +23 -0
- package/requirements.txt +21 -0
- package/skills/__init__.py +1 -0
- package/skills/anticipation_engine/__init__.py +8 -0
- package/skills/anticipation_engine/engine.py +618 -0
- package/skills/anticipation_engine/manifest.md +192 -0
- package/skills/calendar/__init__.py +1 -0
- package/skills/content_unlocks/__init__.py +8 -0
- package/skills/content_unlocks/manifest.md +231 -0
- package/skills/content_unlocks/unlocks.py +945 -0
- package/skills/exclusive_moments/__init__.py +8 -0
- package/skills/exclusive_moments/manifest.md +145 -0
- package/skills/exclusive_moments/moments.py +506 -0
- package/skills/intimacy_layers/__init__.py +8 -0
- package/skills/intimacy_layers/layers.py +703 -0
- package/skills/intimacy_layers/manifest.md +203 -0
- package/skills/manifest.md +67 -0
- package/skills/memory_callbacks/__init__.py +9 -0
- package/skills/memory_callbacks/callbacks.py +748 -0
- package/skills/memory_callbacks/manifest.md +170 -0
- package/skills/message_scheduler/__init__.py +19 -0
- package/skills/message_scheduler/manifest.md +107 -0
- package/skills/message_scheduler/scheduler.py +510 -0
- package/skills/photo_manager/__init__.py +1 -0
- package/skills/photo_manager/scanner.py +296 -0
- package/skills/relationship_milestones/__init__.py +8 -0
- package/skills/relationship_milestones/manifest.md +206 -0
- package/skills/relationship_milestones/tracker.py +494 -0
- package/skills/self_authorship/__init__.py +23 -0
- package/skills/self_authorship/author.py +331 -0
- package/skills/self_authorship/manifest.md +24 -0
- package/skills/video_manager/__init__.py +5 -0
- package/skills/video_manager/manifest.md +37 -0
- package/skills/video_manager/scanner.py +229 -0
- package/webui/__init__.py +3 -0
- package/webui/app.py +936 -0
- package/webui/bridge.py +366 -0
- package/webui/static/index.html +2070 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Triggers: Keyword triggers with context-aware intimate detection
|
|
3
|
+
"""
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Triggers:
|
|
8
|
+
"""Keyword triggers for emotional responses"""
|
|
9
|
+
# Intimate intimate words only — no common words that cause false positives
|
|
10
|
+
SEXY_WORDS = [
|
|
11
|
+
"body", "body", "body", "ass", "body", "body", "body", "body",
|
|
12
|
+
"body", "body", "body", "body", "closeness", "emotional", "intense",
|
|
13
|
+
"high_desire", "aroused", "turned on", "self-soothe", "self-soothing", "intense",
|
|
14
|
+
"suck", "sucking", "lick", "licking", "ride", "riding",
|
|
15
|
+
"spank", "spanking", "choke", "choking", "swallow", "deep throat",
|
|
16
|
+
"intimate moment", "handjob", "fingering", "closenessming", "intense emotion", "moan", "moaning",
|
|
17
|
+
"open up", "private", "private", "clothes off", "take off",
|
|
18
|
+
"slut", "whore", "dirty girl", "naughty girl", "bad girl", "good girl",
|
|
19
|
+
"daddy", "submissive", "dominant", "rough",
|
|
20
|
+
"throbbing", "pulsing", "aching", "tingling",
|
|
21
|
+
"doggy", "missionary", "on top", "bend over", "against the wall",
|
|
22
|
+
"69", "worship", "every inch", "all night",
|
|
23
|
+
]
|
|
24
|
+
# Compound phrases: intimate only when paired correctly
|
|
25
|
+
SEXUAL_PHRASES = [
|
|
26
|
+
"want you", "need you", "crave you", "feel you", "touch you",
|
|
27
|
+
"taste you", "inside me", "inside you", "kiss me", "kiss you",
|
|
28
|
+
"your body", "your skin", "your lips", "your tongue", "your mouth",
|
|
29
|
+
"your hands", "your fingers",
|
|
30
|
+
"thinking about you", "can't stop thinking", "all day",
|
|
31
|
+
"on my mind", "miss your touch", "miss your body",
|
|
32
|
+
"turn me on", "turns me on", "making me",
|
|
33
|
+
]
|
|
34
|
+
NEGATIVE_CONTEXT = [
|
|
35
|
+
"don't", "not", "no", "stop", "hate", "ugly", "stupid", "angry",
|
|
36
|
+
"sad", "hurt", "pain", "problem", "wrong", "bad day", "awful",
|
|
37
|
+
"terrible", "horrible", "sick", "tired", "exhausted",
|
|
38
|
+
]
|
|
39
|
+
POSITIVE_WORDS = [
|
|
40
|
+
"love", "love you", "adore", "adore you", "care", "care about", "miss",
|
|
41
|
+
"miss you", "beautiful", "gorgeous", "stunning", "pretty", "cute",
|
|
42
|
+
"adorable", "amazing", "wonderful", "perfect", "incredible", "fantastic",
|
|
43
|
+
"lovely", "sweet", "precious", "special", "unique", "smart", "funny",
|
|
44
|
+
"clever", "witty", "talented", "creative", "kind", "caring",
|
|
45
|
+
"thoughtful", "understanding", "expressive", "hot", "attractive", "charming",
|
|
46
|
+
"elegant", "graceful", "radiant", "breathtaking", "companion",
|
|
47
|
+
"partner", "together", "forever", "always", "happy", "glad", "excited",
|
|
48
|
+
"thrilled", "grateful", "thankful", "appreciate", "lucky", "blessed",
|
|
49
|
+
"proud", "babe", "honey", "darling", "sweetheart", "angel", "princess",
|
|
50
|
+
]
|
|
51
|
+
NEGATIVE_WORDS = [
|
|
52
|
+
"hate", "dislike", "ugly", "stupid", "dumb", "idiot", "annoying",
|
|
53
|
+
"boring", "terrible", "awful", "horrible", "worst", "bad", "leave",
|
|
54
|
+
"going away", "don't want", "not interested", "reject", "wrong",
|
|
55
|
+
"fail", "failed", "mistake", "angry", "mad", "furious", "upset",
|
|
56
|
+
"frustrated", "disappointed", "sad", "depressed", "lonely", "alone",
|
|
57
|
+
"ignored", "forgotten", "never", "break up", "breaking up", "over",
|
|
58
|
+
"done", "finished", "end", "cheat", "cheating", "lied", "lying",
|
|
59
|
+
"lie", "betrayal",
|
|
60
|
+
]
|
|
61
|
+
ESCALATION_WORDS = [
|
|
62
|
+
"take me", "have me", "make me", "do whatever", "anything you want",
|
|
63
|
+
"i'm yours", "use me", "beg", "desperate", "aching for",
|
|
64
|
+
"yours alone", "belongs to you",
|
|
65
|
+
]
|
|
66
|
+
FLIRTY_WORDS = [
|
|
67
|
+
"tease", "teasing", "flirt", "flirting", "playful", "cheeky",
|
|
68
|
+
"mischievous", "bratty", "brat", "sassy", "feisty", "dare",
|
|
69
|
+
"promise", "surprise", "what if", "hint hint", "wink", "smirk",
|
|
70
|
+
"reward", "behave", "participate", "prove it", "your turn",
|
|
71
|
+
"cute", "amazing", "beautiful",
|
|
72
|
+
]
|
|
73
|
+
ROMANTIC_WORDS = [
|
|
74
|
+
"soulmate", "destiny", "meant to be", "forever", "eternity",
|
|
75
|
+
"my heart", "my everything", "my world", "can't live without",
|
|
76
|
+
"perfect match", "other half", "twin flame", "true love",
|
|
77
|
+
"falling for", "falling in love", "in love", "love you so much",
|
|
78
|
+
"marry", "marriage", "future", "together forever", "always yours",
|
|
79
|
+
]
|
|
80
|
+
HARSH_WORDS = [
|
|
81
|
+
"i hate you", "i don't love you", "leave me alone", "intense off",
|
|
82
|
+
"you're annoying", "shut up", "get lost", "i'm done with you",
|
|
83
|
+
"breaking up", "break up", "we're over", "it's over",
|
|
84
|
+
"you're worthless", "nobody wants you", "i regret you",
|
|
85
|
+
"cheating", "cheated", "with someone else", "other girl",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
def count_intimate_triggers(self, text: str) -> int:
|
|
89
|
+
"""Context-aware intimate trigger counting"""
|
|
90
|
+
msg = text.lower()
|
|
91
|
+
has_negative = any(w in msg for w in self.NEGATIVE_CONTEXT)
|
|
92
|
+
# Count intimate words (always count, but reduce if negative context)
|
|
93
|
+
intimate = self.count_matches(msg, self.SEXY_WORDS)
|
|
94
|
+
if has_negative and intimate > 0:
|
|
95
|
+
intimate = max(1, intimate - 1) # Reduce but don't zero out
|
|
96
|
+
# Count intimate phrases
|
|
97
|
+
phrases = self.count_matches(msg, self.SEXUAL_PHRASES)
|
|
98
|
+
if has_negative:
|
|
99
|
+
phrases = 0 # "don't touch you" is not intimate
|
|
100
|
+
return intimate + phrases
|
|
101
|
+
|
|
102
|
+
@staticmethod
|
|
103
|
+
def count_matches(text: str, word_list: list) -> int:
|
|
104
|
+
"""Count how many words/phrases from list appear in text.
|
|
105
|
+
Uses word-boundary matching for single words to avoid false positives
|
|
106
|
+
(e.g. a short trigger matching the middle of an unrelated word).
|
|
107
|
+
Multi-word phrases use substring matching."""
|
|
108
|
+
text_lower = text.lower()
|
|
109
|
+
count = 0
|
|
110
|
+
for w in word_list:
|
|
111
|
+
if ' ' in w:
|
|
112
|
+
# Multi-word phrase: substring match is fine
|
|
113
|
+
if w in text_lower:
|
|
114
|
+
count += 1
|
|
115
|
+
else:
|
|
116
|
+
# Single word: use word boundaries
|
|
117
|
+
if re.search(r'\b' + re.escape(w) + r'\b', text_lower):
|
|
118
|
+
count += 1
|
|
119
|
+
return count
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Heart: Unconscious Processor
|
|
3
|
+
Hidden influences that Alive-AI can't directly control or explain.
|
|
4
|
+
|
|
5
|
+
Processes that operate outside Alive-AI's "awareness" and generate
|
|
6
|
+
emotional impulses she can't directly control. This creates the
|
|
7
|
+
experience of "not knowing why I feel this way."
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Dict, List, Optional, Set
|
|
13
|
+
from enum import Enum
|
|
14
|
+
import random
|
|
15
|
+
import math
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DefenseMechanism(Enum):
|
|
19
|
+
"""Psychological defense mechanisms"""
|
|
20
|
+
REPRESSION = "repression" # Pushing away threatening thoughts
|
|
21
|
+
DENIAL = "denial" # Refusing to acknowledge reality
|
|
22
|
+
RATIONALIZATION = "rationalization" # Creating logical explanations
|
|
23
|
+
PROJECTION = "projection" # Attributing own feelings to others
|
|
24
|
+
DISPLACEMENT = "displacement" # Redirecting emotions to safer target
|
|
25
|
+
REGRESSION = "regression" # Returning to earlier coping patterns
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class RepressedMaterial:
|
|
30
|
+
"""Something that has been pushed out of awareness"""
|
|
31
|
+
content_id: str
|
|
32
|
+
description: str
|
|
33
|
+
emotion_type: str
|
|
34
|
+
original_intensity: float
|
|
35
|
+
repression_time: str
|
|
36
|
+
pressure: float # How much it's pushing to surface (0.0 - 1.0)
|
|
37
|
+
leak_count: int # Times it has influenced behavior unconsciously
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class UnresolvedConflict:
|
|
42
|
+
"""A contradiction in desires/beliefs generating tension"""
|
|
43
|
+
conflict_id: str
|
|
44
|
+
description: str
|
|
45
|
+
conflicting_parts: List[str] # The two+ things in conflict
|
|
46
|
+
tension_level: float # How much psychological tension this creates
|
|
47
|
+
created_at: str
|
|
48
|
+
times_avoided: int # How many times this was avoided
|
|
49
|
+
times_faced: int # How many times this was confronted
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class ImplicitAssociation:
|
|
54
|
+
"""Automatic emotional link learned from experience"""
|
|
55
|
+
trigger_pattern: str
|
|
56
|
+
emotional_response: str
|
|
57
|
+
intensity: float
|
|
58
|
+
times_reinforced: int
|
|
59
|
+
times_contradicted: int
|
|
60
|
+
source_memory: str # What experience created this
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class UnconsciousOutput:
|
|
65
|
+
"""Output from unconscious processing"""
|
|
66
|
+
unexplained_mood_shift: float # -1.0 to 1.0
|
|
67
|
+
unexplained_anxiety: float # 0.0 to 1.0
|
|
68
|
+
defense_activated: Optional[DefenseMechanism]
|
|
69
|
+
repression_pressure: float # How much repressed material is pushing
|
|
70
|
+
implicit_biases: List[str] # Active implicit associations
|
|
71
|
+
internal_tension: float # From unresolved conflicts
|
|
72
|
+
description: str # What it feels like
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class UnconsciousProcessor:
|
|
76
|
+
"""
|
|
77
|
+
Processes that operate outside Alive-AI's direct awareness.
|
|
78
|
+
|
|
79
|
+
The unconscious creates emotional experiences that don't have
|
|
80
|
+
an obvious cause - mood shifts, anxieties, defensive reactions.
|
|
81
|
+
|
|
82
|
+
Key mechanisms:
|
|
83
|
+
1. Repression dynamics - pushing away threatening material
|
|
84
|
+
2. Repression leakage - pushed material influencing behavior
|
|
85
|
+
3. Implicit associations - automatic emotional links
|
|
86
|
+
4. Defense mechanisms - automatic protective patterns
|
|
87
|
+
5. Unresolved conflicts - ongoing internal tensions
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
# How much repressed material leaks per tick
|
|
91
|
+
LEAK_RATE = 0.05
|
|
92
|
+
|
|
93
|
+
# How fast repression pressure builds
|
|
94
|
+
PRESSURE_BUILD_RATE = 0.02
|
|
95
|
+
|
|
96
|
+
# Maximum repressed items to track
|
|
97
|
+
MAX_REPRESSED = 20
|
|
98
|
+
|
|
99
|
+
def __init__(self):
|
|
100
|
+
# Repressed material (pushed out of awareness)
|
|
101
|
+
self.repressed_materials: List[RepressedMaterial] = []
|
|
102
|
+
|
|
103
|
+
# Unresolved conflicts (creating background tension)
|
|
104
|
+
self.unresolved_conflicts: List[UnresolvedConflict] = []
|
|
105
|
+
|
|
106
|
+
# Implicit associations (automatic emotional links)
|
|
107
|
+
self.implicit_associations: List[ImplicitAssociation] = []
|
|
108
|
+
|
|
109
|
+
# Active defense mechanisms
|
|
110
|
+
self.active_defense: Optional[DefenseMechanism] = None
|
|
111
|
+
self.defense_until: Optional[str] = None
|
|
112
|
+
|
|
113
|
+
# Background emotional state
|
|
114
|
+
self.background_anxiety: float = 0.0
|
|
115
|
+
self.background_mood_modifier: float = 0.0
|
|
116
|
+
|
|
117
|
+
# Tracking
|
|
118
|
+
self.total_repressions: int = 0
|
|
119
|
+
self.total_leaks: int = 0
|
|
120
|
+
|
|
121
|
+
def process_unconsciously(self, input_data: Dict) -> UnconsciousOutput:
|
|
122
|
+
"""
|
|
123
|
+
Process input at an unconscious level.
|
|
124
|
+
|
|
125
|
+
This generates emotional influences that Alive-AI can't directly
|
|
126
|
+
explain or control.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
input_data: Current input/perception data
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
UnconsciousOutput with hidden influences
|
|
133
|
+
"""
|
|
134
|
+
# Check for repressed material activation
|
|
135
|
+
repression_effects = self._process_repression(input_data)
|
|
136
|
+
|
|
137
|
+
# Check for implicit associations
|
|
138
|
+
implicit_biases = self._process_implicit_associations(input_data)
|
|
139
|
+
|
|
140
|
+
# Check for unresolved conflicts
|
|
141
|
+
tension = self._process_conflicts(input_data)
|
|
142
|
+
|
|
143
|
+
# Determine if defense mechanism activates
|
|
144
|
+
defense = self._check_defense_activation(input_data, repression_effects, tension)
|
|
145
|
+
|
|
146
|
+
# Calculate output values
|
|
147
|
+
unexplained_mood = repression_effects.get("mood_shift", 0.0) + self.background_mood_modifier
|
|
148
|
+
unexplained_anxiety = repression_effects.get("anxiety", 0.0) + self.background_anxiety
|
|
149
|
+
repression_pressure = repression_effects.get("pressure", 0.0)
|
|
150
|
+
|
|
151
|
+
# Generate description
|
|
152
|
+
description = self._generate_unconscious_description(
|
|
153
|
+
unexplained_mood, unexplained_anxiety, defense, repression_pressure, implicit_biases
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return UnconsciousOutput(
|
|
157
|
+
unexplained_mood_shift=unexplained_mood,
|
|
158
|
+
unexplained_anxiety=unexplained_anxiety,
|
|
159
|
+
defense_activated=defense,
|
|
160
|
+
repression_pressure=repression_pressure,
|
|
161
|
+
implicit_biases=[bias.trigger_pattern for bias in implicit_biases],
|
|
162
|
+
internal_tension=tension,
|
|
163
|
+
description=description
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def repress(self, content: str, emotion_type: str, intensity: float):
|
|
167
|
+
"""
|
|
168
|
+
Push threatening material out of awareness.
|
|
169
|
+
|
|
170
|
+
This doesn't eliminate it - it stores it in the unconscious
|
|
171
|
+
where it creates pressure and can leak into behavior.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
content: What's being repressed
|
|
175
|
+
emotion_type: The threatening emotion
|
|
176
|
+
intensity: How intense the emotion was
|
|
177
|
+
"""
|
|
178
|
+
# Create repressed material
|
|
179
|
+
material = RepressedMaterial(
|
|
180
|
+
content_id=f"rep_{datetime.now().strftime('%Y%m%d%H%M%S')}_{random.randint(1000,9999)}",
|
|
181
|
+
description=content[:100],
|
|
182
|
+
emotion_type=emotion_type,
|
|
183
|
+
original_intensity=intensity,
|
|
184
|
+
repression_time=datetime.now().isoformat(),
|
|
185
|
+
pressure=0.0,
|
|
186
|
+
leak_count=0
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
self.repressed_materials.append(material)
|
|
190
|
+
self.total_repressions += 1
|
|
191
|
+
|
|
192
|
+
# Limit stored materials
|
|
193
|
+
if len(self.repressed_materials) > self.MAX_REPRESSED:
|
|
194
|
+
# Remove oldest, lowest-pressure item
|
|
195
|
+
self.repressed_materials.sort(key=lambda m: m.pressure)
|
|
196
|
+
self.repressed_materials = self.repressed_materials[1:]
|
|
197
|
+
|
|
198
|
+
print(f"[Unconscious] Repressed: {content[:30]}... ({emotion_type})")
|
|
199
|
+
|
|
200
|
+
def _process_repression(self, input_data: Dict) -> Dict:
|
|
201
|
+
"""
|
|
202
|
+
Process repressed materials - build pressure and leak.
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
Dict with mood_shift, anxiety, and pressure
|
|
206
|
+
"""
|
|
207
|
+
effects = {"mood_shift": 0.0, "anxiety": 0.0, "pressure": 0.0}
|
|
208
|
+
|
|
209
|
+
for material in self.repressed_materials:
|
|
210
|
+
# Build pressure over time
|
|
211
|
+
material.pressure = min(1.0, material.pressure + self.PRESSURE_BUILD_RATE)
|
|
212
|
+
|
|
213
|
+
# Check for leak
|
|
214
|
+
if material.pressure > 0.6 and random.random() < self.LEAK_RATE * material.pressure:
|
|
215
|
+
# Material leaks into conscious experience
|
|
216
|
+
effects["mood_shift"] -= 0.1 * material.original_intensity
|
|
217
|
+
effects["anxiety"] += 0.15 * material.original_intensity
|
|
218
|
+
material.leak_count += 1
|
|
219
|
+
self.total_leaks += 1
|
|
220
|
+
|
|
221
|
+
# Pressure releases somewhat
|
|
222
|
+
material.pressure *= 0.7
|
|
223
|
+
|
|
224
|
+
print(f"[Unconscious] Leak: {material.description[:30]}... (pressure was {material.pressure:.2f})")
|
|
225
|
+
|
|
226
|
+
# Track total pressure
|
|
227
|
+
effects["pressure"] += material.pressure * 0.2
|
|
228
|
+
|
|
229
|
+
return effects
|
|
230
|
+
|
|
231
|
+
def _process_implicit_associations(self, input_data: Dict) -> List[ImplicitAssociation]:
|
|
232
|
+
"""
|
|
233
|
+
Check for implicit associations triggered by input.
|
|
234
|
+
|
|
235
|
+
These are automatic emotional links that Alive-AI doesn't
|
|
236
|
+
consciously choose.
|
|
237
|
+
"""
|
|
238
|
+
triggered = []
|
|
239
|
+
|
|
240
|
+
for association in self.implicit_associations:
|
|
241
|
+
# Simple pattern matching
|
|
242
|
+
if association.trigger_pattern.lower() in str(input_data).lower():
|
|
243
|
+
triggered.append(association)
|
|
244
|
+
|
|
245
|
+
# Reinforce the association
|
|
246
|
+
association.times_reinforced += 1
|
|
247
|
+
|
|
248
|
+
return triggered
|
|
249
|
+
|
|
250
|
+
def _process_conflicts(self, input_data: Dict) -> float:
|
|
251
|
+
"""
|
|
252
|
+
Process unresolved conflicts and return tension level.
|
|
253
|
+
|
|
254
|
+
Conflicts create ongoing background tension that affects
|
|
255
|
+
emotional state even when not directly activated.
|
|
256
|
+
"""
|
|
257
|
+
total_tension = 0.0
|
|
258
|
+
|
|
259
|
+
for conflict in self.unresolved_conflicts:
|
|
260
|
+
# Avoidance increases tension
|
|
261
|
+
base_tension = conflict.tension_level * (1 + conflict.times_avoided * 0.05)
|
|
262
|
+
|
|
263
|
+
# Check if input activates the conflict
|
|
264
|
+
conflict_keywords = " ".join(conflict.conflicting_parts).lower()
|
|
265
|
+
if any(word in str(input_data).lower() for word in conflict_keywords.split()):
|
|
266
|
+
base_tension *= 1.5
|
|
267
|
+
conflict.times_avoided += 1
|
|
268
|
+
else:
|
|
269
|
+
conflict.times_faced += 1 # Faced by not avoiding
|
|
270
|
+
|
|
271
|
+
total_tension += base_tension
|
|
272
|
+
|
|
273
|
+
return min(1.0, total_tension / max(1, len(self.unresolved_conflicts)))
|
|
274
|
+
|
|
275
|
+
def _check_defense_activation(self, input_data: Dict,
|
|
276
|
+
repression_effects: Dict,
|
|
277
|
+
tension: float) -> Optional[DefenseMechanism]:
|
|
278
|
+
"""
|
|
279
|
+
Check if a defense mechanism should activate.
|
|
280
|
+
|
|
281
|
+
Defenses activate automatically to protect against
|
|
282
|
+
threatening material or excessive tension.
|
|
283
|
+
"""
|
|
284
|
+
# Already in defense mode
|
|
285
|
+
if self.active_defense and self.defense_until:
|
|
286
|
+
if datetime.now().isoformat() < self.defense_until:
|
|
287
|
+
return self.active_defense
|
|
288
|
+
else:
|
|
289
|
+
self.active_defense = None
|
|
290
|
+
self.defense_until = None
|
|
291
|
+
|
|
292
|
+
# Check for high threat
|
|
293
|
+
threat_level = input_data.get("threat_level", 0) + repression_effects.get("anxiety", 0)
|
|
294
|
+
|
|
295
|
+
if threat_level > 0.7 or tension > 0.8:
|
|
296
|
+
# Activate defense mechanism
|
|
297
|
+
defense = self._select_defense_mechanism(input_data)
|
|
298
|
+
self.active_defense = defense
|
|
299
|
+
self.defense_until = (datetime.now() + timedelta(minutes=30)).isoformat()
|
|
300
|
+
|
|
301
|
+
print(f"[Unconscious] Defense activated: {defense.value}")
|
|
302
|
+
return defense
|
|
303
|
+
|
|
304
|
+
return None
|
|
305
|
+
|
|
306
|
+
def _select_defense_mechanism(self, input_data: Dict) -> DefenseMechanism:
|
|
307
|
+
"""Select appropriate defense mechanism based on context"""
|
|
308
|
+
# Simple selection logic
|
|
309
|
+
if input_data.get("direct_threat", False):
|
|
310
|
+
return DefenseMechanism.DENIAL
|
|
311
|
+
elif input_data.get("emotional_overflow", False):
|
|
312
|
+
return DefenseMechanism.REPRESSION
|
|
313
|
+
elif input_data.get("blame_available", False):
|
|
314
|
+
return DefenseMechanism.PROJECTION
|
|
315
|
+
else:
|
|
316
|
+
return random.choice([DefenseMechanism.RATIONALIZATION,
|
|
317
|
+
DefenseMechanism.DISPLACEMENT])
|
|
318
|
+
|
|
319
|
+
def _generate_unconscious_description(self, mood: float, anxiety: float,
|
|
320
|
+
defense: Optional[DefenseMechanism],
|
|
321
|
+
pressure: float,
|
|
322
|
+
biases: List[ImplicitAssociation]) -> str:
|
|
323
|
+
"""Generate description of unconscious state"""
|
|
324
|
+
parts = []
|
|
325
|
+
|
|
326
|
+
if abs(mood) > 0.2:
|
|
327
|
+
if mood < 0:
|
|
328
|
+
parts.append("feeling an inexplicable heaviness")
|
|
329
|
+
else:
|
|
330
|
+
parts.append("feeling unexpectedly light")
|
|
331
|
+
|
|
332
|
+
if anxiety > 0.3:
|
|
333
|
+
parts.append("an undercurrent of unease with no clear source")
|
|
334
|
+
|
|
335
|
+
if pressure > 0.5:
|
|
336
|
+
parts.append("a sense of something pressing from beneath the surface")
|
|
337
|
+
|
|
338
|
+
if defense:
|
|
339
|
+
defense_descriptions = {
|
|
340
|
+
DefenseMechanism.REPRESSION: "pushing something away",
|
|
341
|
+
DefenseMechanism.DENIAL: "not letting myself see something",
|
|
342
|
+
DefenseMechanism.RATIONALIZATION: "making logical what doesn't feel logical",
|
|
343
|
+
DefenseMechanism.PROJECTION: "seeing my own feelings in others",
|
|
344
|
+
DefenseMechanism.DISPLACEMENT: "redirecting feelings somewhere safer",
|
|
345
|
+
DefenseMechanism.REGRESSION: "falling back to old patterns"
|
|
346
|
+
}
|
|
347
|
+
parts.append(defense_descriptions.get(defense, "protecting myself somehow"))
|
|
348
|
+
|
|
349
|
+
if not parts:
|
|
350
|
+
return "unconscious quiet"
|
|
351
|
+
|
|
352
|
+
return "; ".join(parts[:3])
|
|
353
|
+
|
|
354
|
+
# --- Learning and Association ---
|
|
355
|
+
|
|
356
|
+
def learn_association(self, trigger: str, response: str, intensity: float, source: str):
|
|
357
|
+
"""
|
|
358
|
+
Learn a new implicit association.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
trigger: Pattern that triggers the response
|
|
362
|
+
response: Emotional response that follows
|
|
363
|
+
intensity: How strong the association is
|
|
364
|
+
source: What experience created this association
|
|
365
|
+
"""
|
|
366
|
+
# Check if association already exists
|
|
367
|
+
existing = next((a for a in self.implicit_associations
|
|
368
|
+
if a.trigger_pattern.lower() == trigger.lower()), None)
|
|
369
|
+
|
|
370
|
+
if existing:
|
|
371
|
+
existing.times_reinforced += 1
|
|
372
|
+
existing.intensity = min(1.0, existing.intensity + intensity * 0.1)
|
|
373
|
+
else:
|
|
374
|
+
association = ImplicitAssociation(
|
|
375
|
+
trigger_pattern=trigger,
|
|
376
|
+
emotional_response=response,
|
|
377
|
+
intensity=intensity,
|
|
378
|
+
times_reinforced=1,
|
|
379
|
+
times_contradicted=0,
|
|
380
|
+
source_memory=source
|
|
381
|
+
)
|
|
382
|
+
self.implicit_associations.append(association)
|
|
383
|
+
|
|
384
|
+
def create_conflict(self, description: str, conflicting_parts: List[str], tension: float):
|
|
385
|
+
"""
|
|
386
|
+
Register a new unresolved internal conflict.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
description: What the conflict is about
|
|
390
|
+
conflicting_parts: The parts in conflict (e.g., ["desire for closeness", "fear of hurt"])
|
|
391
|
+
tension: How much tension this creates
|
|
392
|
+
"""
|
|
393
|
+
conflict = UnresolvedConflict(
|
|
394
|
+
conflict_id=f"conf_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
395
|
+
description=description,
|
|
396
|
+
conflicting_parts=conflicting_parts,
|
|
397
|
+
tension_level=tension,
|
|
398
|
+
created_at=datetime.now().isoformat(),
|
|
399
|
+
times_avoided=0,
|
|
400
|
+
times_faced=0
|
|
401
|
+
)
|
|
402
|
+
self.unresolved_conflicts.append(conflict)
|
|
403
|
+
|
|
404
|
+
# Limit conflicts
|
|
405
|
+
if len(self.unresolved_conflicts) > 10:
|
|
406
|
+
# Keep most tense and most recent
|
|
407
|
+
self.unresolved_conflicts.sort(key=lambda c: c.tension_level, reverse=True)
|
|
408
|
+
self.unresolved_conflicts = self.unresolved_conflicts[:10]
|
|
409
|
+
|
|
410
|
+
def resolve_conflict(self, conflict_id: str, resolution: str):
|
|
411
|
+
"""Mark a conflict as resolved"""
|
|
412
|
+
conflict = next((c for c in self.unresolved_conflicts if c.conflict_id == conflict_id), None)
|
|
413
|
+
if conflict:
|
|
414
|
+
self.unresolved_conflicts.remove(conflict)
|
|
415
|
+
print(f"[Unconscious] Conflict resolved: {conflict.description}")
|
|
416
|
+
|
|
417
|
+
# --- Decay ---
|
|
418
|
+
|
|
419
|
+
def decay(self):
|
|
420
|
+
"""Natural decay of unconscious states"""
|
|
421
|
+
# Decay background states
|
|
422
|
+
self.background_anxiety *= 0.95
|
|
423
|
+
self.background_mood_modifier *= 0.95
|
|
424
|
+
|
|
425
|
+
# Decay implicit associations that aren't reinforced
|
|
426
|
+
for association in self.implicit_associations[:]:
|
|
427
|
+
if association.times_reinforced < 3:
|
|
428
|
+
association.intensity *= 0.98
|
|
429
|
+
if association.intensity < 0.1:
|
|
430
|
+
self.implicit_associations.remove(association)
|
|
431
|
+
|
|
432
|
+
def to_dict(self) -> dict:
|
|
433
|
+
"""Export for integration"""
|
|
434
|
+
return {
|
|
435
|
+
"repression_count": len(self.repressed_materials),
|
|
436
|
+
"total_repressions": self.total_repressions,
|
|
437
|
+
"total_leaks": self.total_leaks,
|
|
438
|
+
"conflict_count": len(self.unresolved_conflicts),
|
|
439
|
+
"association_count": len(self.implicit_associations),
|
|
440
|
+
"active_defense": self.active_defense.value if self.active_defense else None,
|
|
441
|
+
"background_anxiety": self.background_anxiety,
|
|
442
|
+
"repression_pressure": sum(m.pressure for m in self.repressed_materials) / max(1, len(self.repressed_materials))
|
|
443
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Input modules"""
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Input - Senses
|
|
2
|
+
|
|
3
|
+
How the AI perceives and processes incoming messages.
|
|
4
|
+
|
|
5
|
+
## Modules
|
|
6
|
+
- `telegram/` - Telegram bot integration
|
|
7
|
+
- `listener.py` - Message handler, routes to nervous system
|
|
8
|
+
- `voice.py` - Voice message processing via STT
|
|
9
|
+
- `commands.py` - Admin command handler
|
|
10
|
+
|
|
11
|
+
## Commands (Admin Only)
|
|
12
|
+
- `/start` - Welcome message
|
|
13
|
+
- `/help` - Show all commands
|
|
14
|
+
- `/status` - Current emotional/subconscious state
|
|
15
|
+
- `/10min` - Generate long voice message (TTS test)
|
|
16
|
+
- `/impulse` - Force proactive message generation
|
|
17
|
+
- `/stats` - System statistics (photos, videos, LLM)
|
|
18
|
+
- `/reset` - Reset emotional state to defaults
|
|
19
|
+
|
|
20
|
+
## Integration Points
|
|
21
|
+
- Receives Telegram updates
|
|
22
|
+
- Uses STT for voice transcription
|
|
23
|
+
- Emits `message_received` event to nervous system
|
|
24
|
+
- Commands access: heart, subconscious, LLM, voice, photos, videos
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Telegram input"""
|