lex-agentic-language 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 +6 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +13 -0
- data/lex-agentic-language.gemspec +30 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/client.rb +25 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/blend.rb +91 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/blending_engine.rb +171 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/constants.rb +35 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/mental_space.rb +51 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/runners/conceptual_blending.rb +106 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/conceptual_blending.rb +20 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/client.rb +19 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/constants.rb +49 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor.rb +109 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_engine.rb +154 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor.rb +107 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/conceptual_metaphor.rb +19 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/helpers/client.rb +23 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/helpers/constants.rb +32 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame.rb +109 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame_engine.rb +139 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame_instance.rb +51 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/runners/frame_semantics.rb +108 -0
- data/lib/legion/extensions/agentic/language/frame_semantics/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/frame_semantics.rb +20 -0
- data/lib/legion/extensions/agentic/language/grammar/client.rb +29 -0
- data/lib/legion/extensions/agentic/language/grammar/helpers/constants.rb +38 -0
- data/lib/legion/extensions/agentic/language/grammar/helpers/construal.rb +68 -0
- data/lib/legion/extensions/agentic/language/grammar/helpers/construction.rb +68 -0
- data/lib/legion/extensions/agentic/language/grammar/helpers/grammar_engine.rb +119 -0
- data/lib/legion/extensions/agentic/language/grammar/runners/cognitive_grammar.rb +100 -0
- data/lib/legion/extensions/agentic/language/grammar/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/grammar.rb +20 -0
- data/lib/legion/extensions/agentic/language/inner_speech/client.rb +19 -0
- data/lib/legion/extensions/agentic/language/inner_speech/helpers/constants.rb +53 -0
- data/lib/legion/extensions/agentic/language/inner_speech/helpers/inner_voice.rb +141 -0
- data/lib/legion/extensions/agentic/language/inner_speech/helpers/speech_stream.rb +128 -0
- data/lib/legion/extensions/agentic/language/inner_speech/helpers/utterance.rb +90 -0
- data/lib/legion/extensions/agentic/language/inner_speech/runners/inner_speech.rb +87 -0
- data/lib/legion/extensions/agentic/language/inner_speech/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/inner_speech.rb +20 -0
- data/lib/legion/extensions/agentic/language/language/client.rb +26 -0
- data/lib/legion/extensions/agentic/language/language/helpers/constants.rb +43 -0
- data/lib/legion/extensions/agentic/language/language/helpers/lexicon.rb +63 -0
- data/lib/legion/extensions/agentic/language/language/helpers/summarizer.rb +167 -0
- data/lib/legion/extensions/agentic/language/language/runners/language.rb +134 -0
- data/lib/legion/extensions/agentic/language/language/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/language.rb +19 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/client.rb +28 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative.rb +123 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_engine.rb +122 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_event.rb +41 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/runners/narrative_reasoning.rb +122 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/narrative_reasoning.rb +18 -0
- data/lib/legion/extensions/agentic/language/narrator/client.rb +27 -0
- data/lib/legion/extensions/agentic/language/narrator/helpers/constants.rb +69 -0
- data/lib/legion/extensions/agentic/language/narrator/helpers/journal.rb +68 -0
- data/lib/legion/extensions/agentic/language/narrator/helpers/llm_enhancer.rb +105 -0
- data/lib/legion/extensions/agentic/language/narrator/helpers/prose.rb +122 -0
- data/lib/legion/extensions/agentic/language/narrator/helpers/synthesizer.rb +138 -0
- data/lib/legion/extensions/agentic/language/narrator/runners/narrator.rb +196 -0
- data/lib/legion/extensions/agentic/language/narrator/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/narrator.rb +21 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/client.rb +28 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/constants.rb +52 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/pragmatic_engine.rb +164 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/utterance.rb +84 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/runners/pragmatic_inference.rb +136 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference/version.rb +13 -0
- data/lib/legion/extensions/agentic/language/pragmatic_inference.rb +18 -0
- data/lib/legion/extensions/agentic/language/version.rb +11 -0
- data/lib/legion/extensions/agentic/language.rb +28 -0
- data/spec/legion/extensions/agentic/language/conceptual_blending/client_spec.rb +78 -0
- data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/blend_spec.rb +141 -0
- data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/blending_engine_spec.rb +211 -0
- data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/mental_space_spec.rb +85 -0
- data/spec/legion/extensions/agentic/language/conceptual_blending/runners/conceptual_blending_spec.rb +162 -0
- data/spec/legion/extensions/agentic/language/conceptual_metaphor/client_spec.rb +29 -0
- data/spec/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_engine_spec.rb +166 -0
- data/spec/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_spec.rb +133 -0
- data/spec/legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor_spec.rb +133 -0
- data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_engine_spec.rb +227 -0
- data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_instance_spec.rb +83 -0
- data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_spec.rb +213 -0
- data/spec/legion/extensions/agentic/language/frame_semantics/runners/frame_semantics_spec.rb +155 -0
- data/spec/legion/extensions/agentic/language/grammar/client_spec.rb +121 -0
- data/spec/legion/extensions/agentic/language/grammar/cognitive_grammar_spec.rb +18 -0
- data/spec/legion/extensions/agentic/language/grammar/helpers/constants_spec.rb +67 -0
- data/spec/legion/extensions/agentic/language/grammar/helpers/construal_spec.rb +124 -0
- data/spec/legion/extensions/agentic/language/grammar/helpers/construction_spec.rb +155 -0
- data/spec/legion/extensions/agentic/language/grammar/helpers/grammar_engine_spec.rb +206 -0
- data/spec/legion/extensions/agentic/language/grammar/runners/cognitive_grammar_spec.rb +189 -0
- data/spec/legion/extensions/agentic/language/inner_speech/client_spec.rb +39 -0
- data/spec/legion/extensions/agentic/language/inner_speech/helpers/inner_voice_spec.rb +185 -0
- data/spec/legion/extensions/agentic/language/inner_speech/helpers/speech_stream_spec.rb +158 -0
- data/spec/legion/extensions/agentic/language/inner_speech/helpers/utterance_spec.rb +121 -0
- data/spec/legion/extensions/agentic/language/inner_speech/runners/inner_speech_spec.rb +102 -0
- data/spec/legion/extensions/agentic/language/language/client_spec.rb +20 -0
- data/spec/legion/extensions/agentic/language/language/helpers/constants_spec.rb +31 -0
- data/spec/legion/extensions/agentic/language/language/helpers/lexicon_spec.rb +116 -0
- data/spec/legion/extensions/agentic/language/language/helpers/summarizer_spec.rb +224 -0
- data/spec/legion/extensions/agentic/language/language/runners/language_spec.rb +169 -0
- data/spec/legion/extensions/agentic/language/narrative_reasoning/client_spec.rb +19 -0
- data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_engine_spec.rb +182 -0
- data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_event_spec.rb +61 -0
- data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_spec.rb +168 -0
- data/spec/legion/extensions/agentic/language/narrative_reasoning/runners/narrative_reasoning_spec.rb +174 -0
- data/spec/legion/extensions/agentic/language/narrator/client_spec.rb +24 -0
- data/spec/legion/extensions/agentic/language/narrator/helpers/journal_spec.rb +95 -0
- data/spec/legion/extensions/agentic/language/narrator/helpers/llm_enhancer_spec.rb +107 -0
- data/spec/legion/extensions/agentic/language/narrator/helpers/prose_spec.rb +134 -0
- data/spec/legion/extensions/agentic/language/narrator/helpers/synthesizer_spec.rb +89 -0
- data/spec/legion/extensions/agentic/language/narrator/runners/narrator_llm_spec.rb +74 -0
- data/spec/legion/extensions/agentic/language/narrator/runners/narrator_spec.rb +126 -0
- data/spec/legion/extensions/agentic/language/pragmatic_inference/client_spec.rb +19 -0
- data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/constants_spec.rb +73 -0
- data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/pragmatic_engine_spec.rb +185 -0
- data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/utterance_spec.rb +111 -0
- data/spec/legion/extensions/agentic/language/pragmatic_inference/runners/pragmatic_inference_spec.rb +231 -0
- data/spec/spec_helper.rb +33 -0
- metadata +210 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module Narrator
|
|
8
|
+
module Helpers
|
|
9
|
+
module Prose
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def emotion_phrase(valence: 0.0, arousal: 0.5, gut: nil)
|
|
13
|
+
emotion_label = emotion_label_for(valence)
|
|
14
|
+
arousal_label = arousal_label_for(arousal)
|
|
15
|
+
base = "I am #{arousal_label} and #{emotion_label}"
|
|
16
|
+
gut_note = gut_phrase(gut)
|
|
17
|
+
gut_note ? "#{base}. #{gut_note}" : base
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def curiosity_phrase(intensity: 0.0, top_wonder: nil, wonder_count: 0)
|
|
21
|
+
label = curiosity_label_for(intensity)
|
|
22
|
+
base = "I am #{label}"
|
|
23
|
+
if top_wonder && wonder_count.positive?
|
|
24
|
+
"#{base}, with #{wonder_count} open #{'question' if wonder_count == 1}#{'questions' if wonder_count != 1}. " \
|
|
25
|
+
"Most pressing: \"#{top_wonder}\""
|
|
26
|
+
else
|
|
27
|
+
base
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def prediction_phrase(confidence: 0.0, pending: 0, mode: nil)
|
|
32
|
+
label = confidence_label_for(confidence)
|
|
33
|
+
base = "I am #{label}"
|
|
34
|
+
base += " (#{mode} reasoning)" if mode
|
|
35
|
+
base += ", with #{pending} pending predictions" if pending.positive?
|
|
36
|
+
base
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def attention_phrase(spotlight: 0, peripheral: 0, focused_domains: [])
|
|
40
|
+
parts = ["#{spotlight} signals in spotlight focus, #{peripheral} in peripheral awareness"]
|
|
41
|
+
parts << "manually focused on: #{focused_domains.join(', ')}" if focused_domains.any?
|
|
42
|
+
parts.join('. ')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def memory_phrase(trace_count: 0, health: 1.0)
|
|
46
|
+
health_label = health_label_for(health)
|
|
47
|
+
"Memory system #{health_label} with #{trace_count} active traces"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def reflection_phrase(health: 1.0, pending_adaptations: 0, recent_severity: nil)
|
|
51
|
+
label = health_label_for(health)
|
|
52
|
+
base = "Cognitive health: #{label}"
|
|
53
|
+
base += ". #{pending_adaptations} pending adaptation recommendations" if pending_adaptations.positive?
|
|
54
|
+
base += ". Most recent concern: #{recent_severity}" if recent_severity
|
|
55
|
+
base
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def overall_narrative(sections)
|
|
59
|
+
"#{sections.compact.reject(&:empty?).join('. ')}."
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def gut_phrase(gut)
|
|
63
|
+
return nil unless gut.is_a?(Hash)
|
|
64
|
+
|
|
65
|
+
signal = gut[:signal] || gut[:gut_signal]
|
|
66
|
+
return nil unless signal
|
|
67
|
+
|
|
68
|
+
if signal > 0.3
|
|
69
|
+
'My gut says something important is happening'
|
|
70
|
+
elsif signal < -0.3
|
|
71
|
+
'I have an uneasy feeling about the current situation'
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def emotion_label_for(valence)
|
|
76
|
+
if valence > 0.5 then Constants::EMOTION_LABELS[:high_positive]
|
|
77
|
+
elsif valence > 0.1 then Constants::EMOTION_LABELS[:low_positive]
|
|
78
|
+
elsif valence > -0.1 then Constants::EMOTION_LABELS[:neutral]
|
|
79
|
+
elsif valence > -0.5 then Constants::EMOTION_LABELS[:low_negative]
|
|
80
|
+
else Constants::EMOTION_LABELS[:high_negative]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def arousal_label_for(arousal)
|
|
85
|
+
if arousal > 0.7 then Constants::AROUSAL_LABELS[:high]
|
|
86
|
+
elsif arousal > 0.4 then Constants::AROUSAL_LABELS[:medium]
|
|
87
|
+
elsif arousal > 0.1 then Constants::AROUSAL_LABELS[:low]
|
|
88
|
+
else Constants::AROUSAL_LABELS[:dormant]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def curiosity_label_for(intensity)
|
|
93
|
+
if intensity > 0.7 then Constants::CURIOSITY_LABELS[:high]
|
|
94
|
+
elsif intensity > 0.4 then Constants::CURIOSITY_LABELS[:medium]
|
|
95
|
+
elsif intensity > 0.1 then Constants::CURIOSITY_LABELS[:low]
|
|
96
|
+
else Constants::CURIOSITY_LABELS[:none]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def confidence_label_for(confidence)
|
|
101
|
+
if confidence > 0.7 then Constants::CONFIDENCE_LABELS[:high]
|
|
102
|
+
elsif confidence > 0.4 then Constants::CONFIDENCE_LABELS[:medium]
|
|
103
|
+
elsif confidence > 0.1 then Constants::CONFIDENCE_LABELS[:low]
|
|
104
|
+
else Constants::CONFIDENCE_LABELS[:none]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def health_label_for(health)
|
|
109
|
+
if health > 0.9 then Constants::HEALTH_LABELS[:excellent]
|
|
110
|
+
elsif health > 0.7 then Constants::HEALTH_LABELS[:good]
|
|
111
|
+
elsif health > 0.5 then Constants::HEALTH_LABELS[:fair]
|
|
112
|
+
elsif health > 0.3 then Constants::HEALTH_LABELS[:poor]
|
|
113
|
+
else Constants::HEALTH_LABELS[:critical]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module Narrator
|
|
8
|
+
module Helpers
|
|
9
|
+
module Synthesizer
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def narrate(tick_results: {}, cognitive_state: {})
|
|
13
|
+
sections = build_sections(tick_results, cognitive_state)
|
|
14
|
+
narrative = Prose.overall_narrative(sections.values)
|
|
15
|
+
mood = infer_mood(tick_results, cognitive_state)
|
|
16
|
+
|
|
17
|
+
{
|
|
18
|
+
timestamp: Time.now.utc,
|
|
19
|
+
narrative: narrative,
|
|
20
|
+
sections: sections,
|
|
21
|
+
mood: mood,
|
|
22
|
+
tick_seq: tick_results[:tick_seq] || cognitive_state[:tick_seq]
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def build_sections(tick_results, cognitive_state)
|
|
27
|
+
{
|
|
28
|
+
attention: synthesize_attention(tick_results, cognitive_state),
|
|
29
|
+
emotion: synthesize_emotion(tick_results, cognitive_state),
|
|
30
|
+
curiosity: synthesize_curiosity(tick_results, cognitive_state),
|
|
31
|
+
prediction: synthesize_prediction(tick_results, cognitive_state),
|
|
32
|
+
memory: synthesize_memory(tick_results, cognitive_state),
|
|
33
|
+
reflection: synthesize_reflection(cognitive_state)
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def synthesize_attention(tick_results, cognitive_state)
|
|
38
|
+
attention = tick_results[:sensory_processing] || {}
|
|
39
|
+
focus = cognitive_state[:attention_status] || {}
|
|
40
|
+
|
|
41
|
+
Prose.attention_phrase(
|
|
42
|
+
spotlight: attention[:spotlight] || 0,
|
|
43
|
+
peripheral: attention[:peripheral] || 0,
|
|
44
|
+
focused_domains: extract_focused_domains(focus)
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def synthesize_emotion(tick_results, cognitive_state)
|
|
49
|
+
valence_data = tick_results[:emotional_evaluation] || {}
|
|
50
|
+
gut_data = tick_results[:gut_instinct] || cognitive_state[:gut] || {}
|
|
51
|
+
|
|
52
|
+
Prose.emotion_phrase(
|
|
53
|
+
valence: valence_data[:valence] || cognitive_state.dig(:emotion, :valence) || 0.0,
|
|
54
|
+
arousal: valence_data[:arousal] || cognitive_state.dig(:emotion, :arousal) || 0.5,
|
|
55
|
+
gut: gut_data
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def synthesize_curiosity(tick_results, cognitive_state)
|
|
60
|
+
curiosity_data = cognitive_state[:curiosity] || {}
|
|
61
|
+
wonder_data = tick_results[:working_memory_integration] || {}
|
|
62
|
+
|
|
63
|
+
Prose.curiosity_phrase(
|
|
64
|
+
intensity: curiosity_data[:intensity] || wonder_data[:curiosity_intensity] || 0.0,
|
|
65
|
+
top_wonder: extract_top_wonder(curiosity_data, wonder_data),
|
|
66
|
+
wonder_count: curiosity_data[:active_count] || wonder_data[:active_wonders] || 0
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def synthesize_prediction(tick_results, cognitive_state)
|
|
71
|
+
pred_data = tick_results[:prediction_engine] || {}
|
|
72
|
+
pred_state = cognitive_state[:prediction] || {}
|
|
73
|
+
|
|
74
|
+
Prose.prediction_phrase(
|
|
75
|
+
confidence: pred_data[:confidence] || pred_state[:confidence] || 0.0,
|
|
76
|
+
pending: pred_state[:pending_count] || 0,
|
|
77
|
+
mode: pred_data[:mode] || pred_state[:mode]
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def synthesize_memory(tick_results, cognitive_state)
|
|
82
|
+
memory_data = cognitive_state[:memory] || {}
|
|
83
|
+
consol = tick_results[:memory_consolidation] || {}
|
|
84
|
+
|
|
85
|
+
Prose.memory_phrase(
|
|
86
|
+
trace_count: memory_data[:trace_count] || consol[:remaining] || 0,
|
|
87
|
+
health: memory_data[:health] || 1.0
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def synthesize_reflection(cognitive_state)
|
|
92
|
+
ref_data = cognitive_state[:reflection] || {}
|
|
93
|
+
|
|
94
|
+
Prose.reflection_phrase(
|
|
95
|
+
health: ref_data[:health] || 1.0,
|
|
96
|
+
pending_adaptations: ref_data[:pending_adaptations] || 0,
|
|
97
|
+
recent_severity: ref_data[:recent_severity]
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def infer_mood(tick_results, cognitive_state)
|
|
102
|
+
valence = tick_results.dig(:emotional_evaluation, :valence) ||
|
|
103
|
+
cognitive_state.dig(:emotion, :valence) || 0.0
|
|
104
|
+
arousal = tick_results.dig(:emotional_evaluation, :arousal) ||
|
|
105
|
+
cognitive_state.dig(:emotion, :arousal) || 0.5
|
|
106
|
+
|
|
107
|
+
classify_mood(valence, arousal)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def classify_mood(valence, arousal)
|
|
111
|
+
if valence > 0.3 && arousal > 0.5 then :energized
|
|
112
|
+
elsif valence > 0.3 then :content
|
|
113
|
+
elsif valence < -0.3 && arousal > 0.5 then :anxious
|
|
114
|
+
elsif valence < -0.3 then :subdued
|
|
115
|
+
elsif arousal > 0.7 then :alert
|
|
116
|
+
elsif arousal < 0.2 then :dormant
|
|
117
|
+
else :neutral
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def extract_focused_domains(focus)
|
|
122
|
+
manual = focus[:manual_focus]
|
|
123
|
+
return [] unless manual.is_a?(Hash)
|
|
124
|
+
|
|
125
|
+
manual.keys.map(&:to_s)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def extract_top_wonder(curiosity_data, wonder_data)
|
|
129
|
+
curiosity_data[:top_question] || wonder_data[:top_question] ||
|
|
130
|
+
(wonder_data[:top_wonder].is_a?(Hash) ? wonder_data[:top_wonder][:question] : nil)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module Narrator
|
|
8
|
+
module Runners
|
|
9
|
+
module Narrator
|
|
10
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
11
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
12
|
+
|
|
13
|
+
def narrate(tick_results: {}, cognitive_state: {}, **)
|
|
14
|
+
entry = Helpers::Synthesizer.narrate(tick_results: tick_results, cognitive_state: cognitive_state)
|
|
15
|
+
|
|
16
|
+
if Helpers::LlmEnhancer.available?
|
|
17
|
+
sections_data = build_llm_sections_data(tick_results, cognitive_state, entry)
|
|
18
|
+
llm_result = Helpers::LlmEnhancer.narrate(sections_data: sections_data)
|
|
19
|
+
if llm_result
|
|
20
|
+
entry = entry.merge(narrative: llm_result, source: :llm)
|
|
21
|
+
journal.append(entry)
|
|
22
|
+
Legion::Logging.debug "[narrator] mood=#{entry[:mood]} source=llm sections=#{entry[:sections].keys.size}"
|
|
23
|
+
return {
|
|
24
|
+
narrative: entry[:narrative],
|
|
25
|
+
mood: entry[:mood],
|
|
26
|
+
timestamp: entry[:timestamp],
|
|
27
|
+
sections: entry[:sections],
|
|
28
|
+
source: :llm
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
journal.append(entry)
|
|
34
|
+
Legion::Logging.debug "[narrator] mood=#{entry[:mood]} sections=#{entry[:sections].keys.size}"
|
|
35
|
+
|
|
36
|
+
{
|
|
37
|
+
narrative: entry[:narrative],
|
|
38
|
+
mood: entry[:mood],
|
|
39
|
+
timestamp: entry[:timestamp],
|
|
40
|
+
sections: entry[:sections]
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def recent_entries(limit: 10, **)
|
|
45
|
+
entries = journal.recent(limit: limit)
|
|
46
|
+
{
|
|
47
|
+
entries: entries.map { |e| format_entry(e) },
|
|
48
|
+
count: entries.size,
|
|
49
|
+
total: journal.size
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def entries_since(since:, **)
|
|
54
|
+
timestamp = since.is_a?(Time) ? since : Time.parse(since.to_s)
|
|
55
|
+
entries = journal.since(timestamp)
|
|
56
|
+
{
|
|
57
|
+
entries: entries.map { |e| format_entry(e) },
|
|
58
|
+
count: entries.size,
|
|
59
|
+
since: timestamp
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def mood_history(mood: nil, limit: 20, **)
|
|
64
|
+
entries = mood ? journal.by_mood(mood.to_sym) : journal.entries
|
|
65
|
+
recent = entries.last(limit)
|
|
66
|
+
{
|
|
67
|
+
entries: recent.map { |e| { timestamp: e[:timestamp], mood: e[:mood], narrative: e[:narrative] } },
|
|
68
|
+
count: recent.size,
|
|
69
|
+
mood: mood
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def current_narrative(**)
|
|
74
|
+
entry = journal.entries.last
|
|
75
|
+
return { narrative: 'No cognitive activity recorded yet.', mood: :dormant } unless entry
|
|
76
|
+
|
|
77
|
+
{
|
|
78
|
+
narrative: entry[:narrative],
|
|
79
|
+
mood: entry[:mood],
|
|
80
|
+
timestamp: entry[:timestamp],
|
|
81
|
+
age_seconds: (Time.now.utc - entry[:timestamp]).round(1)
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def narrator_stats(**)
|
|
86
|
+
stats = journal.stats
|
|
87
|
+
mood_summary = stats[:moods] || {}
|
|
88
|
+
dominant_mood = mood_summary.max_by { |_, count| count }&.first
|
|
89
|
+
|
|
90
|
+
{
|
|
91
|
+
journal_size: journal.size,
|
|
92
|
+
capacity: Helpers::Constants::MAX_JOURNAL_SIZE,
|
|
93
|
+
dominant_mood: dominant_mood,
|
|
94
|
+
mood_counts: mood_summary,
|
|
95
|
+
oldest: stats[:oldest],
|
|
96
|
+
newest: stats[:newest]
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def journal
|
|
103
|
+
@journal ||= Helpers::Journal.new
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def build_llm_sections_data(tick_results, cognitive_state, entry)
|
|
107
|
+
{
|
|
108
|
+
emotion: llm_emotion_data(tick_results, cognitive_state),
|
|
109
|
+
curiosity: llm_curiosity_data(tick_results, cognitive_state),
|
|
110
|
+
prediction: llm_prediction_data(tick_results, cognitive_state),
|
|
111
|
+
memory: llm_memory_data(tick_results, cognitive_state),
|
|
112
|
+
attention: llm_attention_data(tick_results, cognitive_state),
|
|
113
|
+
reflection: llm_reflection_data(cognitive_state),
|
|
114
|
+
mood: entry[:mood]
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def llm_emotion_data(tick_results, cognitive_state)
|
|
119
|
+
v = tick_results[:emotional_evaluation] || {}
|
|
120
|
+
g = tick_results[:gut_instinct] || cognitive_state[:gut] || {}
|
|
121
|
+
{
|
|
122
|
+
valence: v[:valence] || cognitive_state.dig(:emotion, :valence) || 0.0,
|
|
123
|
+
arousal: v[:arousal] || cognitive_state.dig(:emotion, :arousal) || 0.5,
|
|
124
|
+
gut: g[:signal] || g[:gut_signal]
|
|
125
|
+
}
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def llm_curiosity_data(tick_results, cognitive_state)
|
|
129
|
+
c = cognitive_state[:curiosity] || {}
|
|
130
|
+
w = tick_results[:working_memory_integration] || {}
|
|
131
|
+
{
|
|
132
|
+
intensity: c[:intensity] || w[:curiosity_intensity] || 0.0,
|
|
133
|
+
wonder_count: c[:active_count] || w[:active_wonders] || 0,
|
|
134
|
+
top_wonder: c[:top_question] || w[:top_question]
|
|
135
|
+
}
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def llm_prediction_data(tick_results, cognitive_state)
|
|
139
|
+
p = tick_results[:prediction_engine] || {}
|
|
140
|
+
s = cognitive_state[:prediction] || {}
|
|
141
|
+
{
|
|
142
|
+
confidence: p[:confidence] || s[:confidence] || 0.0,
|
|
143
|
+
pending: s[:pending_count] || 0,
|
|
144
|
+
mode: p[:mode] || s[:mode]
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def llm_memory_data(tick_results, cognitive_state)
|
|
149
|
+
m = cognitive_state[:memory] || {}
|
|
150
|
+
c = tick_results[:memory_consolidation] || {}
|
|
151
|
+
{
|
|
152
|
+
trace_count: m[:trace_count] || c[:remaining] || 0,
|
|
153
|
+
health: m[:health] || 1.0
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def llm_attention_data(tick_results, cognitive_state)
|
|
158
|
+
a = tick_results[:sensory_processing] || {}
|
|
159
|
+
f = cognitive_state[:attention_status] || {}
|
|
160
|
+
{
|
|
161
|
+
spotlight: a[:spotlight] || 0,
|
|
162
|
+
peripheral: a[:peripheral] || 0,
|
|
163
|
+
focused_domains: extract_focused_domains_for_llm(f)
|
|
164
|
+
}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def llm_reflection_data(cognitive_state)
|
|
168
|
+
r = cognitive_state[:reflection] || {}
|
|
169
|
+
{
|
|
170
|
+
health: r[:health] || 1.0,
|
|
171
|
+
pending_adaptations: r[:pending_adaptations] || 0
|
|
172
|
+
}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def extract_focused_domains_for_llm(focus)
|
|
176
|
+
manual = focus[:manual_focus]
|
|
177
|
+
return [] unless manual.is_a?(Hash)
|
|
178
|
+
|
|
179
|
+
manual.keys.map(&:to_s)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def format_entry(entry)
|
|
183
|
+
{
|
|
184
|
+
timestamp: entry[:timestamp],
|
|
185
|
+
narrative: entry[:narrative],
|
|
186
|
+
mood: entry[:mood],
|
|
187
|
+
sections: entry[:sections]
|
|
188
|
+
}
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/language/narrator/version'
|
|
4
|
+
require 'legion/extensions/agentic/language/narrator/helpers/constants'
|
|
5
|
+
require 'legion/extensions/agentic/language/narrator/helpers/prose'
|
|
6
|
+
require 'legion/extensions/agentic/language/narrator/helpers/journal'
|
|
7
|
+
require 'legion/extensions/agentic/language/narrator/helpers/synthesizer'
|
|
8
|
+
require 'legion/extensions/agentic/language/narrator/helpers/llm_enhancer'
|
|
9
|
+
require 'legion/extensions/agentic/language/narrator/runners/narrator'
|
|
10
|
+
require 'legion/extensions/agentic/language/narrator/client'
|
|
11
|
+
|
|
12
|
+
module Legion
|
|
13
|
+
module Extensions
|
|
14
|
+
module Agentic
|
|
15
|
+
module Language
|
|
16
|
+
module Narrator
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/language/pragmatic_inference/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/language/pragmatic_inference/helpers/utterance'
|
|
5
|
+
require 'legion/extensions/agentic/language/pragmatic_inference/helpers/pragmatic_engine'
|
|
6
|
+
require 'legion/extensions/agentic/language/pragmatic_inference/runners/pragmatic_inference'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Agentic
|
|
11
|
+
module Language
|
|
12
|
+
module PragmaticInference
|
|
13
|
+
class Client
|
|
14
|
+
include Runners::PragmaticInference
|
|
15
|
+
|
|
16
|
+
def initialize(**)
|
|
17
|
+
@engine = Helpers::PragmaticEngine.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
attr_reader :engine
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module PragmaticInference
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
MAX_UTTERANCES = 500
|
|
11
|
+
MAX_IMPLICATURES = 200
|
|
12
|
+
MAX_HISTORY = 300
|
|
13
|
+
|
|
14
|
+
DEFAULT_CONFIDENCE = 0.5
|
|
15
|
+
CONFIDENCE_FLOOR = 0.0
|
|
16
|
+
CONFIDENCE_CEILING = 1.0
|
|
17
|
+
REINFORCEMENT_RATE = 0.1
|
|
18
|
+
DECAY_RATE = 0.02
|
|
19
|
+
|
|
20
|
+
MAXIMS = %i[quality quantity relevance manner].freeze
|
|
21
|
+
|
|
22
|
+
VIOLATION_TYPES = %i[none flouting violating opting_out].freeze
|
|
23
|
+
|
|
24
|
+
SPEECH_ACTS = %i[assert question request promise warn inform suggest].freeze
|
|
25
|
+
|
|
26
|
+
MAXIM_DESCRIPTIONS = {
|
|
27
|
+
quality: 'be truthful, have evidence',
|
|
28
|
+
quantity: 'be informative, not more than needed',
|
|
29
|
+
relevance: 'be relevant to the conversation',
|
|
30
|
+
manner: 'be clear, brief, orderly, unambiguous'
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
module_function
|
|
34
|
+
|
|
35
|
+
def valid_maxim?(maxim)
|
|
36
|
+
MAXIMS.include?(maxim)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def valid_violation_type?(type)
|
|
40
|
+
VIOLATION_TYPES.include?(type)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def valid_speech_act?(act)
|
|
44
|
+
SPEECH_ACTS.include?(act)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|