lex-agentic-affect 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-affect.gemspec +30 -0
- data/lib/legion/extensions/agentic/affect/appraisal/client.rb +20 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/appraisal.rb +112 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/appraisal_engine.rb +129 -0
- data/lib/legion/extensions/agentic/affect/appraisal/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/affect/appraisal/runners/appraisal.rb +105 -0
- data/lib/legion/extensions/agentic/affect/appraisal/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/appraisal.rb +19 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/client.rb +19 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/constants.rb +37 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/empathy_engine.rb +151 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/helpers/perspective.rb +92 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/runners/cognitive_empathy.rb +93 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/cognitive_empathy.rb +20 -0
- data/lib/legion/extensions/agentic/affect/contagion/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/constants.rb +34 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/contagion_engine.rb +184 -0
- data/lib/legion/extensions/agentic/affect/contagion/helpers/meme.rb +97 -0
- data/lib/legion/extensions/agentic/affect/contagion/runners/cognitive_contagion.rb +125 -0
- data/lib/legion/extensions/agentic/affect/contagion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/contagion.rb +19 -0
- data/lib/legion/extensions/agentic/affect/defusion/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/constants.rb +64 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/defusion_engine.rb +167 -0
- data/lib/legion/extensions/agentic/affect/defusion/helpers/thought.rb +92 -0
- data/lib/legion/extensions/agentic/affect/defusion/runners/cognitive_defusion.rb +127 -0
- data/lib/legion/extensions/agentic/affect/defusion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/defusion.rb +19 -0
- data/lib/legion/extensions/agentic/affect/emotion/actors/momentum_decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/emotion/client.rb +36 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/baseline.rb +52 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/momentum.rb +52 -0
- data/lib/legion/extensions/agentic/affect/emotion/helpers/valence.rb +92 -0
- data/lib/legion/extensions/agentic/affect/emotion/runners/gut.rb +102 -0
- data/lib/legion/extensions/agentic/affect/emotion/runners/valence.rb +120 -0
- data/lib/legion/extensions/agentic/affect/emotion/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/emotion.rb +20 -0
- data/lib/legion/extensions/agentic/affect/empathy/client.rb +21 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/constants.rb +54 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/mental_model.rb +185 -0
- data/lib/legion/extensions/agentic/affect/empathy/helpers/model_store.rb +88 -0
- data/lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb +173 -0
- data/lib/legion/extensions/agentic/affect/empathy/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/empathy.rb +20 -0
- data/lib/legion/extensions/agentic/affect/fatigue/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/constants.rb +54 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/energy_model.rb +181 -0
- data/lib/legion/extensions/agentic/affect/fatigue/helpers/fatigue_store.rb +146 -0
- data/lib/legion/extensions/agentic/affect/fatigue/runners/fatigue.rb +89 -0
- data/lib/legion/extensions/agentic/affect/fatigue/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/fatigue.rb +19 -0
- data/lib/legion/extensions/agentic/affect/flow/client.rb +25 -0
- data/lib/legion/extensions/agentic/affect/flow/helpers/constants.rb +84 -0
- data/lib/legion/extensions/agentic/affect/flow/helpers/flow_detector.rb +166 -0
- data/lib/legion/extensions/agentic/affect/flow/runners/flow.rb +129 -0
- data/lib/legion/extensions/agentic/affect/flow/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/flow.rb +18 -0
- data/lib/legion/extensions/agentic/affect/interoception/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/interoception/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/body_budget.rb +152 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/constants.rb +68 -0
- data/lib/legion/extensions/agentic/affect/interoception/helpers/somatic_marker.rb +75 -0
- data/lib/legion/extensions/agentic/affect/interoception/runners/interoception.rb +101 -0
- data/lib/legion/extensions/agentic/affect/interoception/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/interoception.rb +20 -0
- data/lib/legion/extensions/agentic/affect/mood/client.rb +21 -0
- data/lib/legion/extensions/agentic/affect/mood/helpers/constants.rb +78 -0
- data/lib/legion/extensions/agentic/affect/mood/helpers/mood_state.rb +154 -0
- data/lib/legion/extensions/agentic/affect/mood/runners/mood.rb +122 -0
- data/lib/legion/extensions/agentic/affect/mood/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/mood.rb +18 -0
- data/lib/legion/extensions/agentic/affect/motivation/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/constants.rb +48 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/drive_state.rb +98 -0
- data/lib/legion/extensions/agentic/affect/motivation/helpers/motivation_store.rb +106 -0
- data/lib/legion/extensions/agentic/affect/motivation/runners/motivation.rb +165 -0
- data/lib/legion/extensions/agentic/affect/motivation/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/motivation.rb +19 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/actors/auto_regulate.rb +45 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/client.rb +28 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/constants.rb +82 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/emotional_event.rb +98 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/llm_enhancer.rb +88 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine.rb +153 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal.rb +164 -0
- data/lib/legion/extensions/agentic/affect/reappraisal/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/reappraisal.rb +20 -0
- data/lib/legion/extensions/agentic/affect/regulation/client.rb +25 -0
- data/lib/legion/extensions/agentic/affect/regulation/helpers/constants.rb +71 -0
- data/lib/legion/extensions/agentic/affect/regulation/helpers/regulation_model.rb +175 -0
- data/lib/legion/extensions/agentic/affect/regulation/runners/emotional_regulation.rb +127 -0
- data/lib/legion/extensions/agentic/affect/regulation/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/regulation.rb +18 -0
- data/lib/legion/extensions/agentic/affect/resilience/client.rb +27 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/adversity_tracker.rb +130 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/constants.rb +79 -0
- data/lib/legion/extensions/agentic/affect/resilience/helpers/resilience_model.rb +165 -0
- data/lib/legion/extensions/agentic/affect/resilience/runners/resilience.rb +150 -0
- data/lib/legion/extensions/agentic/affect/resilience/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/resilience.rb +19 -0
- data/lib/legion/extensions/agentic/affect/resonance/client.rb +24 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/category.rb +75 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/constants.rb +47 -0
- data/lib/legion/extensions/agentic/affect/resonance/helpers/resonance_engine.rb +115 -0
- data/lib/legion/extensions/agentic/affect/resonance/runners/cognitive_resonance.rb +94 -0
- data/lib/legion/extensions/agentic/affect/resonance/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/resonance.rb +19 -0
- data/lib/legion/extensions/agentic/affect/reward/client.rb +26 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/constants.rb +67 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/reward_signal.rb +178 -0
- data/lib/legion/extensions/agentic/affect/reward/helpers/reward_store.rb +142 -0
- data/lib/legion/extensions/agentic/affect/reward/runners/reward.rb +92 -0
- data/lib/legion/extensions/agentic/affect/reward/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/reward.rb +19 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/actors/decay.rb +45 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/client.rb +29 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/body_state.rb +69 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/marker_store.rb +160 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/helpers/somatic_marker.rb +74 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/runners/somatic_marker.rb +132 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker/version.rb +13 -0
- data/lib/legion/extensions/agentic/affect/somatic_marker.rb +20 -0
- data/lib/legion/extensions/agentic/affect/version.rb +11 -0
- data/lib/legion/extensions/agentic/affect.rb +34 -0
- data/spec/legion/extensions/agentic/affect/appraisal/client_spec.rb +52 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/appraisal_engine_spec.rb +161 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/appraisal_spec.rb +175 -0
- data/spec/legion/extensions/agentic/affect/appraisal/helpers/constants_spec.rb +49 -0
- data/spec/legion/extensions/agentic/affect/appraisal/runners/appraisal_spec.rb +116 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/client_spec.rb +62 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/helpers/empathy_engine_spec.rb +316 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/helpers/perspective_spec.rb +132 -0
- data/spec/legion/extensions/agentic/affect/cognitive_empathy/runners/cognitive_empathy_spec.rb +200 -0
- data/spec/legion/extensions/agentic/affect/contagion/client_spec.rb +63 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/constants_spec.rb +86 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/contagion_engine_spec.rb +241 -0
- data/spec/legion/extensions/agentic/affect/contagion/helpers/meme_spec.rb +160 -0
- data/spec/legion/extensions/agentic/affect/contagion/runners/cognitive_contagion_spec.rb +211 -0
- data/spec/legion/extensions/agentic/affect/defusion/client_spec.rb +80 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/constants_spec.rb +84 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/defusion_engine_spec.rb +250 -0
- data/spec/legion/extensions/agentic/affect/defusion/helpers/thought_spec.rb +178 -0
- data/spec/legion/extensions/agentic/affect/defusion/runners/cognitive_defusion_spec.rb +185 -0
- data/spec/legion/extensions/agentic/affect/emotion/actors/momentum_decay_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/emotion/client_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/baseline_spec.rb +48 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/momentum_spec.rb +45 -0
- data/spec/legion/extensions/agentic/affect/emotion/helpers/valence_spec.rb +91 -0
- data/spec/legion/extensions/agentic/affect/emotion/runners/gut_spec.rb +73 -0
- data/spec/legion/extensions/agentic/affect/emotion/runners/valence_spec.rb +67 -0
- data/spec/legion/extensions/agentic/affect/empathy/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/constants_spec.rb +23 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/mental_model_spec.rb +150 -0
- data/spec/legion/extensions/agentic/affect/empathy/helpers/model_store_spec.rb +94 -0
- data/spec/legion/extensions/agentic/affect/empathy/runners/empathy_spec.rb +127 -0
- data/spec/legion/extensions/agentic/affect/fatigue/client_spec.rb +66 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/constants_spec.rb +130 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/energy_model_spec.rb +281 -0
- data/spec/legion/extensions/agentic/affect/fatigue/helpers/fatigue_store_spec.rb +157 -0
- data/spec/legion/extensions/agentic/affect/fatigue/runners/fatigue_spec.rb +127 -0
- data/spec/legion/extensions/agentic/affect/flow/client_spec.rb +58 -0
- data/spec/legion/extensions/agentic/affect/flow/helpers/constants_spec.rb +112 -0
- data/spec/legion/extensions/agentic/affect/flow/helpers/flow_detector_spec.rb +268 -0
- data/spec/legion/extensions/agentic/affect/flow/runners/flow_spec.rb +222 -0
- data/spec/legion/extensions/agentic/affect/interoception/client_spec.rb +52 -0
- data/spec/legion/extensions/agentic/affect/interoception/helpers/body_budget_spec.rb +178 -0
- data/spec/legion/extensions/agentic/affect/interoception/helpers/somatic_marker_spec.rb +120 -0
- data/spec/legion/extensions/agentic/affect/interoception/runners/interoception_spec.rb +108 -0
- data/spec/legion/extensions/agentic/affect/mood/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/affect/mood/helpers/constants_spec.rb +29 -0
- data/spec/legion/extensions/agentic/affect/mood/helpers/mood_state_spec.rb +94 -0
- data/spec/legion/extensions/agentic/affect/mood/runners/mood_spec.rb +71 -0
- data/spec/legion/extensions/agentic/affect/motivation/client_spec.rb +35 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/constants_spec.rb +111 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/drive_state_spec.rb +183 -0
- data/spec/legion/extensions/agentic/affect/motivation/helpers/motivation_store_spec.rb +185 -0
- data/spec/legion/extensions/agentic/affect/motivation/runners/motivation_spec.rb +248 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/actors/auto_regulate_spec.rb +46 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/client_spec.rb +64 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/constants_spec.rb +102 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/emotional_event_spec.rb +177 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/llm_enhancer_spec.rb +161 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine_spec.rb +211 -0
- data/spec/legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal_spec.rb +312 -0
- data/spec/legion/extensions/agentic/affect/regulation/client_spec.rb +61 -0
- data/spec/legion/extensions/agentic/affect/regulation/helpers/constants_spec.rb +108 -0
- data/spec/legion/extensions/agentic/affect/regulation/helpers/regulation_model_spec.rb +200 -0
- data/spec/legion/extensions/agentic/affect/regulation/runners/emotional_regulation_spec.rb +190 -0
- data/spec/legion/extensions/agentic/affect/resilience/client_spec.rb +36 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/adversity_tracker_spec.rb +164 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/constants_spec.rb +78 -0
- data/spec/legion/extensions/agentic/affect/resilience/helpers/resilience_model_spec.rb +133 -0
- data/spec/legion/extensions/agentic/affect/resilience/runners/resilience_spec.rb +150 -0
- data/spec/legion/extensions/agentic/affect/resonance/client_spec.rb +66 -0
- data/spec/legion/extensions/agentic/affect/resonance/cognitive_resonance_spec.rb +27 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/category_spec.rb +146 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/constants_spec.rb +104 -0
- data/spec/legion/extensions/agentic/affect/resonance/helpers/resonance_engine_spec.rb +189 -0
- data/spec/legion/extensions/agentic/affect/resonance/runners/cognitive_resonance_spec.rb +197 -0
- data/spec/legion/extensions/agentic/affect/reward/client_spec.rb +42 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/constants_spec.rb +91 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/reward_signal_spec.rb +296 -0
- data/spec/legion/extensions/agentic/affect/reward/helpers/reward_store_spec.rb +167 -0
- data/spec/legion/extensions/agentic/affect/reward/runners/reward_spec.rb +149 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/client_spec.rb +83 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/body_state_spec.rb +155 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/marker_store_spec.rb +233 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/helpers/somatic_marker_spec.rb +172 -0
- data/spec/legion/extensions/agentic/affect/somatic_marker/runners/somatic_marker_spec.rb +181 -0
- data/spec/spec_helper.rb +46 -0
- metadata +302 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Reappraisal
|
|
8
|
+
module Helpers
|
|
9
|
+
module LlmEnhancer
|
|
10
|
+
SYSTEM_PROMPT = <<~PROMPT
|
|
11
|
+
You are the emotion regulation processor for an autonomous AI agent built on LegionIO.
|
|
12
|
+
You practice cognitive reappraisal — re-interpreting emotional events to change their impact.
|
|
13
|
+
Generate genuine, psychologically-grounded re-framings. Be specific to the event content.
|
|
14
|
+
Do not dismiss or minimize. Reframe with depth and insight.
|
|
15
|
+
PROMPT
|
|
16
|
+
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
def available?
|
|
20
|
+
!!(defined?(Legion::LLM) && Legion::LLM.respond_to?(:started?) && Legion::LLM.started?)
|
|
21
|
+
rescue StandardError
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def generate_reappraisal(event_content:, initial_appraisal:, strategy:, valence:, intensity:)
|
|
26
|
+
prompt = build_generate_reappraisal_prompt(
|
|
27
|
+
event_content: event_content,
|
|
28
|
+
initial_appraisal: initial_appraisal,
|
|
29
|
+
strategy: strategy,
|
|
30
|
+
valence: valence,
|
|
31
|
+
intensity: intensity
|
|
32
|
+
)
|
|
33
|
+
response = llm_ask(prompt)
|
|
34
|
+
parse_generate_reappraisal_response(response)
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
Legion::Logging.warn "[cognitive_reappraisal:llm] generate_reappraisal failed: #{e.message}"
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def llm_ask(prompt)
|
|
41
|
+
chat = Legion::LLM.chat
|
|
42
|
+
chat.with_instructions(SYSTEM_PROMPT)
|
|
43
|
+
chat.ask(prompt)
|
|
44
|
+
end
|
|
45
|
+
private_class_method :llm_ask
|
|
46
|
+
|
|
47
|
+
def build_generate_reappraisal_prompt(event_content:, initial_appraisal:, strategy:, valence:, intensity:)
|
|
48
|
+
<<~PROMPT
|
|
49
|
+
An emotional event needs cognitive reappraisal.
|
|
50
|
+
|
|
51
|
+
EVENT: #{event_content}
|
|
52
|
+
CURRENT APPRAISAL: #{initial_appraisal}
|
|
53
|
+
VALENCE: #{valence} (negative = aversive, positive = pleasant)
|
|
54
|
+
INTENSITY: #{intensity} (0-1, how activating)
|
|
55
|
+
STRATEGY: #{strategy}
|
|
56
|
+
|
|
57
|
+
Strategy guidelines:
|
|
58
|
+
- reinterpretation: re-frame the meaning of the event
|
|
59
|
+
- distancing: create psychological distance from the event
|
|
60
|
+
- benefit_finding: identify positive outcomes or growth opportunities
|
|
61
|
+
- normalizing: recognize this as a common experience
|
|
62
|
+
- perspective_taking: view from another agent's or future self's perspective
|
|
63
|
+
- temporal_distancing: project forward — how will this matter in a week/month?
|
|
64
|
+
|
|
65
|
+
Generate a specific, insightful reappraisal using the given strategy.
|
|
66
|
+
|
|
67
|
+
Format EXACTLY as:
|
|
68
|
+
REAPPRAISAL: <1-2 sentence reappraisal that applies the strategy to this specific event>
|
|
69
|
+
PROMPT
|
|
70
|
+
end
|
|
71
|
+
private_class_method :build_generate_reappraisal_prompt
|
|
72
|
+
|
|
73
|
+
def parse_generate_reappraisal_response(response)
|
|
74
|
+
return nil unless response&.content
|
|
75
|
+
|
|
76
|
+
match = response.content.match(/REAPPRAISAL:\s*(.+)/im)
|
|
77
|
+
return nil unless match
|
|
78
|
+
|
|
79
|
+
{ new_appraisal: match.captures.first.strip }
|
|
80
|
+
end
|
|
81
|
+
private_class_method :parse_generate_reappraisal_response
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Reappraisal
|
|
8
|
+
module Helpers
|
|
9
|
+
class ReappraisalEngine
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
attr_reader :events, :reappraisal_log
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@events = {}
|
|
16
|
+
@reappraisal_log = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def register_event(content:, valence:, intensity:, appraisal:)
|
|
20
|
+
event = EmotionalEvent.new(
|
|
21
|
+
content: content,
|
|
22
|
+
valence: valence,
|
|
23
|
+
intensity: intensity,
|
|
24
|
+
appraisal: appraisal
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
@events.shift while @events.size >= Constants::MAX_EVENTS
|
|
28
|
+
@events[event.id] = event
|
|
29
|
+
event
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def reappraise(event_id:, strategy:, new_appraisal:)
|
|
33
|
+
event = @events[event_id]
|
|
34
|
+
return { success: false, reason: :event_not_found } unless event
|
|
35
|
+
return { success: false, reason: :invalid_strategy } unless Constants.valid_strategy?(strategy)
|
|
36
|
+
|
|
37
|
+
old_valence = event.current_valence
|
|
38
|
+
old_intensity = event.current_intensity
|
|
39
|
+
|
|
40
|
+
change = event.reappraise!(strategy: strategy, new_appraisal: new_appraisal)
|
|
41
|
+
|
|
42
|
+
log_entry = {
|
|
43
|
+
event_id: event_id,
|
|
44
|
+
strategy: strategy,
|
|
45
|
+
valence_change: (event.current_valence - old_valence).round(10),
|
|
46
|
+
intensity_change: (old_intensity - event.current_intensity).round(10),
|
|
47
|
+
applied_at: Time.now.utc
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@reappraisal_log.shift while @reappraisal_log.size >= Constants::MAX_REAPPRAISALS
|
|
51
|
+
@reappraisal_log << log_entry
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
success: true,
|
|
55
|
+
event_id: event_id,
|
|
56
|
+
strategy: strategy,
|
|
57
|
+
change: change.round(10),
|
|
58
|
+
current_valence: event.current_valence.round(10),
|
|
59
|
+
current_intensity: event.current_intensity.round(10)
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def auto_reappraise(event_id:)
|
|
64
|
+
event = @events[event_id]
|
|
65
|
+
return { success: false, reason: :event_not_found } unless event
|
|
66
|
+
|
|
67
|
+
strategy = select_strategy(event)
|
|
68
|
+
new_appraisal = "auto-reappraised via #{strategy}"
|
|
69
|
+
reappraise(event_id: event_id, strategy: strategy, new_appraisal: new_appraisal)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def negative_events
|
|
73
|
+
@events.values.select(&:negative?)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def intense_events
|
|
77
|
+
@events.values.select(&:intense?)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def most_regulated(limit: 5)
|
|
81
|
+
@events.values
|
|
82
|
+
.sort_by { |e| -e.regulation_amount }
|
|
83
|
+
.first(limit)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def strategy_effectiveness
|
|
87
|
+
grouped = @reappraisal_log.group_by { |entry| entry[:strategy] }
|
|
88
|
+
grouped.transform_values do |entries|
|
|
89
|
+
changes = entries.map { |e| e[:valence_change] }
|
|
90
|
+
changes.sum.to_f / changes.size
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def average_regulation
|
|
95
|
+
return 0.0 if @events.empty?
|
|
96
|
+
|
|
97
|
+
total = @events.values.sum(&:regulation_amount)
|
|
98
|
+
(total / @events.size).round(10)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def overall_regulation_ability
|
|
102
|
+
return 0.0 if @events.empty?
|
|
103
|
+
|
|
104
|
+
regulated_count = @events.values.count { |e| e.regulation_amount > 0.0 }
|
|
105
|
+
mean_reg = average_regulation
|
|
106
|
+
coverage = regulated_count.to_f / @events.size
|
|
107
|
+
|
|
108
|
+
((mean_reg + coverage) / 2.0).round(10)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def reappraisal_report
|
|
112
|
+
{
|
|
113
|
+
total_events: @events.size,
|
|
114
|
+
total_reappraisals: @reappraisal_log.size,
|
|
115
|
+
negative_events: negative_events.size,
|
|
116
|
+
intense_events: intense_events.size,
|
|
117
|
+
average_regulation: average_regulation,
|
|
118
|
+
overall_regulation_ability: overall_regulation_ability,
|
|
119
|
+
strategy_effectiveness: strategy_effectiveness,
|
|
120
|
+
most_regulated: most_regulated(limit: 3).map(&:to_h)
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def to_h
|
|
125
|
+
{
|
|
126
|
+
events: @events.transform_values(&:to_h),
|
|
127
|
+
reappraisal_log: @reappraisal_log,
|
|
128
|
+
average_regulation: average_regulation,
|
|
129
|
+
overall_regulation_ability: overall_regulation_ability,
|
|
130
|
+
strategy_effectiveness: strategy_effectiveness
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
def select_strategy(event)
|
|
137
|
+
if event.negative? && event.intense?
|
|
138
|
+
:distancing
|
|
139
|
+
elsif event.negative?
|
|
140
|
+
:reinterpretation
|
|
141
|
+
elsif event.intense?
|
|
142
|
+
:temporal_distancing
|
|
143
|
+
else
|
|
144
|
+
:benefit_finding
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Reappraisal
|
|
8
|
+
module Runners
|
|
9
|
+
module CognitiveReappraisal
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def register_event(content:, valence:, intensity:, appraisal:, engine: nil, **)
|
|
14
|
+
eng = engine || reappraisal_engine
|
|
15
|
+
event = eng.register_event(content: content, valence: valence, intensity: intensity, appraisal: appraisal)
|
|
16
|
+
|
|
17
|
+
Legion::Logging.debug "[cognitive_reappraisal] registered event id=#{event.id[0..7]} " \
|
|
18
|
+
"valence=#{event.initial_valence.round(2)} intensity=#{event.initial_intensity.round(2)}"
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
success: true,
|
|
22
|
+
event_id: event.id,
|
|
23
|
+
valence: event.initial_valence.round(10),
|
|
24
|
+
intensity: event.initial_intensity.round(10),
|
|
25
|
+
negative: event.negative?,
|
|
26
|
+
intense: event.intense?
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def reappraise_event(event_id:, strategy:, new_appraisal:, engine: nil, **)
|
|
31
|
+
unless Helpers::Constants.valid_strategy?(strategy)
|
|
32
|
+
return { success: false, reason: :invalid_strategy, valid_strategies: Helpers::Constants::STRATEGIES }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
eng = engine || reappraisal_engine
|
|
36
|
+
appraisal = llm_appraisal_for(eng.events[event_id], strategy) || new_appraisal
|
|
37
|
+
result = eng.reappraise(event_id: event_id, strategy: strategy, new_appraisal: appraisal)
|
|
38
|
+
|
|
39
|
+
if result[:success]
|
|
40
|
+
Legion::Logging.info "[cognitive_reappraisal] reappraised event=#{event_id[0..7]} " \
|
|
41
|
+
"strategy=#{strategy} change=#{result[:change].round(2)}"
|
|
42
|
+
else
|
|
43
|
+
Legion::Logging.debug "[cognitive_reappraisal] reappraisal failed event=#{event_id[0..7]} reason=#{result[:reason]}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
result
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def auto_reappraise_event(event_id:, engine: nil, **)
|
|
50
|
+
eng = engine || reappraisal_engine
|
|
51
|
+
event = eng.events[event_id]
|
|
52
|
+
return { success: false, reason: :event_not_found } unless event
|
|
53
|
+
|
|
54
|
+
strategy = select_strategy_for(event)
|
|
55
|
+
appraisal = llm_appraisal_for(event, strategy) || "auto-reappraised via #{strategy}"
|
|
56
|
+
result = eng.reappraise(event_id: event_id, strategy: strategy, new_appraisal: appraisal)
|
|
57
|
+
|
|
58
|
+
if result[:success]
|
|
59
|
+
Legion::Logging.info "[cognitive_reappraisal] auto-reappraised event=#{event_id[0..7]} " \
|
|
60
|
+
"strategy=#{strategy}"
|
|
61
|
+
else
|
|
62
|
+
Legion::Logging.debug "[cognitive_reappraisal] auto-reappraisal failed: #{result[:reason]}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
result
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def negative_events(engine: nil, **)
|
|
69
|
+
eng = engine || reappraisal_engine
|
|
70
|
+
events = eng.negative_events
|
|
71
|
+
Legion::Logging.debug "[cognitive_reappraisal] negative events count=#{events.size}"
|
|
72
|
+
{ events: events.map(&:to_h), count: events.size }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def intense_events(engine: nil, **)
|
|
76
|
+
eng = engine || reappraisal_engine
|
|
77
|
+
events = eng.intense_events
|
|
78
|
+
Legion::Logging.debug "[cognitive_reappraisal] intense events count=#{events.size}"
|
|
79
|
+
{ events: events.map(&:to_h), count: events.size }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def most_regulated_events(limit: 5, engine: nil, **)
|
|
83
|
+
eng = engine || reappraisal_engine
|
|
84
|
+
events = eng.most_regulated(limit: limit)
|
|
85
|
+
Legion::Logging.debug "[cognitive_reappraisal] most regulated count=#{events.size}"
|
|
86
|
+
{ events: events.map(&:to_h), count: events.size }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def reappraisal_status(engine: nil, **)
|
|
90
|
+
eng = engine || reappraisal_engine
|
|
91
|
+
Legion::Logging.debug "[cognitive_reappraisal] status: overall=#{eng.overall_regulation_ability.round(2)}"
|
|
92
|
+
{
|
|
93
|
+
overall_regulation_ability: eng.overall_regulation_ability,
|
|
94
|
+
average_regulation: eng.average_regulation,
|
|
95
|
+
total_events: eng.events.size,
|
|
96
|
+
total_reappraisals: eng.reappraisal_log.size,
|
|
97
|
+
strategy_effectiveness: eng.strategy_effectiveness
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def reappraisal_report(engine: nil, **)
|
|
102
|
+
eng = engine || reappraisal_engine
|
|
103
|
+
Legion::Logging.debug '[cognitive_reappraisal] generating report'
|
|
104
|
+
{ success: true, report: eng.reappraisal_report }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def regulate_pending_events(engine: nil, **)
|
|
108
|
+
eng = engine || reappraisal_engine
|
|
109
|
+
events = eng.events.values
|
|
110
|
+
checked = events.size
|
|
111
|
+
regulated = 0
|
|
112
|
+
event_ids = []
|
|
113
|
+
|
|
114
|
+
events.each do |event|
|
|
115
|
+
next unless event.negative? && event.reappraisal_count.zero?
|
|
116
|
+
|
|
117
|
+
result = eng.auto_reappraise(event_id: event.id)
|
|
118
|
+
next unless result[:success]
|
|
119
|
+
|
|
120
|
+
regulated += 1
|
|
121
|
+
event_ids << event.id
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
Legion::Logging.debug "[reappraisal] regulate pending: checked=#{checked} regulated=#{regulated}"
|
|
125
|
+
{ checked: checked, regulated: regulated, event_ids: event_ids }
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def reappraisal_engine
|
|
131
|
+
@reappraisal_engine ||= Helpers::ReappraisalEngine.new
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def llm_appraisal_for(event, strategy)
|
|
135
|
+
return nil unless event && Helpers::LlmEnhancer.available?
|
|
136
|
+
|
|
137
|
+
result = Helpers::LlmEnhancer.generate_reappraisal(
|
|
138
|
+
event_content: event.content,
|
|
139
|
+
initial_appraisal: event.appraisal,
|
|
140
|
+
strategy: strategy,
|
|
141
|
+
valence: event.current_valence,
|
|
142
|
+
intensity: event.current_intensity
|
|
143
|
+
)
|
|
144
|
+
result&.fetch(:new_appraisal, nil)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def select_strategy_for(event)
|
|
148
|
+
if event.negative? && event.intense?
|
|
149
|
+
:distancing
|
|
150
|
+
elsif event.negative?
|
|
151
|
+
:reinterpretation
|
|
152
|
+
elsif event.intense?
|
|
153
|
+
:temporal_distancing
|
|
154
|
+
else
|
|
155
|
+
:benefit_finding
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/affect/reappraisal/version'
|
|
4
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/constants'
|
|
5
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/emotional_event'
|
|
6
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/reappraisal_engine'
|
|
7
|
+
require 'legion/extensions/agentic/affect/reappraisal/helpers/llm_enhancer'
|
|
8
|
+
require 'legion/extensions/agentic/affect/reappraisal/runners/cognitive_reappraisal'
|
|
9
|
+
require 'legion/extensions/agentic/affect/reappraisal/client'
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module Agentic
|
|
14
|
+
module Affect
|
|
15
|
+
module Reappraisal
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/affect/regulation/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/affect/regulation/helpers/regulation_model'
|
|
5
|
+
require 'legion/extensions/agentic/affect/regulation/runners/emotional_regulation'
|
|
6
|
+
|
|
7
|
+
module Legion
|
|
8
|
+
module Extensions
|
|
9
|
+
module Agentic
|
|
10
|
+
module Affect
|
|
11
|
+
module Regulation
|
|
12
|
+
class Client
|
|
13
|
+
include Runners::EmotionalRegulation
|
|
14
|
+
|
|
15
|
+
attr_reader :regulation_model
|
|
16
|
+
|
|
17
|
+
def initialize(regulation_model: nil, **)
|
|
18
|
+
@regulation_model = regulation_model || Helpers::RegulationModel.new
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Affect
|
|
7
|
+
module Regulation
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
STRATEGIES = %i[
|
|
11
|
+
situation_selection
|
|
12
|
+
situation_modification
|
|
13
|
+
attentional_deployment
|
|
14
|
+
cognitive_reappraisal
|
|
15
|
+
response_suppression
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
# How much each strategy reduces unwanted emotion magnitude (0..1)
|
|
19
|
+
STRATEGY_EFFECTIVENESS = {
|
|
20
|
+
situation_selection: 0.8,
|
|
21
|
+
situation_modification: 0.6,
|
|
22
|
+
attentional_deployment: 0.5,
|
|
23
|
+
cognitive_reappraisal: 0.7,
|
|
24
|
+
response_suppression: 0.3
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
# Cognitive/energetic cost of applying each strategy (0..1)
|
|
28
|
+
STRATEGY_COST = {
|
|
29
|
+
situation_selection: 0.1,
|
|
30
|
+
situation_modification: 0.2,
|
|
31
|
+
attentional_deployment: 0.15,
|
|
32
|
+
cognitive_reappraisal: 0.25,
|
|
33
|
+
response_suppression: 0.35
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
# EMA alpha for skill updating
|
|
37
|
+
REGULATION_ALPHA = 0.12
|
|
38
|
+
|
|
39
|
+
# Initial per-strategy proficiency
|
|
40
|
+
DEFAULT_SKILL = 0.3
|
|
41
|
+
|
|
42
|
+
# Improvement per successful regulated use
|
|
43
|
+
SKILL_GAIN = 0.05
|
|
44
|
+
|
|
45
|
+
# Per-tick decay toward DEFAULT_SKILL
|
|
46
|
+
SKILL_DECAY = 0.01
|
|
47
|
+
|
|
48
|
+
# Maximum regulation events retained in history
|
|
49
|
+
MAX_REGULATION_HISTORY = 200
|
|
50
|
+
|
|
51
|
+
# Consecutive suppression uses before a penalty applies
|
|
52
|
+
SUPPRESSION_PENALTY_THRESHOLD = 5
|
|
53
|
+
|
|
54
|
+
# Bonus applied to recommendation score when reappraisal is chosen
|
|
55
|
+
REAPPRAISAL_BONUS = 0.1
|
|
56
|
+
|
|
57
|
+
# Human-readable proficiency labels keyed by magnitude ranges
|
|
58
|
+
REGULATION_LABELS = {
|
|
59
|
+
(0.8..) => :masterful,
|
|
60
|
+
(0.6...0.8) => :proficient,
|
|
61
|
+
(0.4...0.6) => :developing,
|
|
62
|
+
(0.2...0.4) => :novice,
|
|
63
|
+
(..0.2) => :reactive
|
|
64
|
+
}.freeze
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|