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,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module FrameSemantics
|
|
8
|
+
module Helpers
|
|
9
|
+
class FrameEngine
|
|
10
|
+
def initialize
|
|
11
|
+
@frames = {}
|
|
12
|
+
@instances = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create_frame(name:, domain:, slots: {})
|
|
16
|
+
frame = Frame.new(name: name, domain: domain)
|
|
17
|
+
slots.each do |slot_name, opts|
|
|
18
|
+
frame.add_slot(
|
|
19
|
+
name: slot_name,
|
|
20
|
+
slot_type: opts.fetch(:type, :core),
|
|
21
|
+
required: opts.fetch(:required, true)
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
prune_frames_if_full
|
|
25
|
+
@frames[frame.id] = frame
|
|
26
|
+
frame
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def define_slot(frame_id:, name:, slot_type: :core, required: true)
|
|
30
|
+
frame = @frames[frame_id]
|
|
31
|
+
return nil unless frame
|
|
32
|
+
|
|
33
|
+
frame.add_slot(name: name, slot_type: slot_type, required: required)
|
|
34
|
+
frame
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def fill_slot(frame_id:, slot_name:, filler:)
|
|
38
|
+
frame = @frames[frame_id]
|
|
39
|
+
return false unless frame
|
|
40
|
+
|
|
41
|
+
result = frame.fill_slot(name: slot_name, filler: filler)
|
|
42
|
+
frame.activate! if result
|
|
43
|
+
result
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def instantiate_frame(frame_id:, context:, confidence: 0.7)
|
|
47
|
+
frame = @frames[frame_id]
|
|
48
|
+
return nil unless frame
|
|
49
|
+
|
|
50
|
+
fillers = frame.slots.transform_values { |v| v[:filler] }
|
|
51
|
+
instance = FrameInstance.new(
|
|
52
|
+
frame_id: frame_id,
|
|
53
|
+
frame_name: frame.name,
|
|
54
|
+
slot_fillers: fillers,
|
|
55
|
+
context: context,
|
|
56
|
+
confidence: confidence
|
|
57
|
+
)
|
|
58
|
+
@instances << instance
|
|
59
|
+
@instances.shift while @instances.size > MAX_INSTANCES
|
|
60
|
+
instance
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def add_frame_relation(frame_id:, relation:, target_frame_id:)
|
|
64
|
+
frame = @frames[frame_id]
|
|
65
|
+
return false unless frame
|
|
66
|
+
return false unless FRAME_RELATIONS.include?(relation)
|
|
67
|
+
|
|
68
|
+
frame.add_relation(relation: relation, target_frame_id: target_frame_id)
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def activate_frame(frame_id:)
|
|
73
|
+
frame = @frames[frame_id]
|
|
74
|
+
return false unless frame
|
|
75
|
+
|
|
76
|
+
frame.activate!
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def active_frames
|
|
81
|
+
@frames.values.select { |f| f.activation > 0.5 }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def frames_by_domain(domain:)
|
|
85
|
+
@frames.values.select { |f| f.domain == domain }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def related_frames(frame_id:)
|
|
89
|
+
frame = @frames[frame_id]
|
|
90
|
+
return [] unless frame
|
|
91
|
+
|
|
92
|
+
frame.relations.filter_map { |rel| @frames[rel[:target_frame_id]] }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def most_activated(limit: 5)
|
|
96
|
+
@frames.values.sort_by { |f| -f.activation }.first(limit)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def instances_for_frame(frame_id:)
|
|
100
|
+
@instances.select { |i| i.frame_id == frame_id }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def complete_frames
|
|
104
|
+
@frames.values.select(&:complete?)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def decay_all
|
|
108
|
+
@frames.each_value(&:decay!)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def prune_inactive
|
|
112
|
+
@frames.reject! { |_id, f| f.activation <= 0.05 }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def to_h
|
|
116
|
+
{
|
|
117
|
+
frame_count: @frames.size,
|
|
118
|
+
instance_count: @instances.size,
|
|
119
|
+
active_count: active_frames.size,
|
|
120
|
+
complete_count: complete_frames.size,
|
|
121
|
+
domains: @frames.values.map(&:domain).uniq.sort
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
def prune_frames_if_full
|
|
128
|
+
return unless @frames.size >= MAX_FRAMES
|
|
129
|
+
|
|
130
|
+
oldest = @frames.values.min_by(&:activation)
|
|
131
|
+
@frames.delete(oldest.id) if oldest
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Language
|
|
9
|
+
module FrameSemantics
|
|
10
|
+
module Helpers
|
|
11
|
+
class FrameInstance
|
|
12
|
+
attr_reader :id, :frame_id, :frame_name, :slot_fillers, :context, :confidence, :created_at
|
|
13
|
+
|
|
14
|
+
def initialize(frame_id:, frame_name:, slot_fillers:, context:, confidence: 0.7)
|
|
15
|
+
@id = SecureRandom.uuid
|
|
16
|
+
@frame_id = frame_id
|
|
17
|
+
@frame_name = frame_name
|
|
18
|
+
@slot_fillers = slot_fillers.dup
|
|
19
|
+
@context = context
|
|
20
|
+
@confidence = confidence
|
|
21
|
+
@created_at = Time.now.utc
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def complete?
|
|
25
|
+
filled_count.positive?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def filled_count
|
|
29
|
+
@slot_fillers.count { |_k, v| !v.nil? }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_h
|
|
33
|
+
{
|
|
34
|
+
id: @id,
|
|
35
|
+
frame_id: @frame_id,
|
|
36
|
+
frame_name: @frame_name,
|
|
37
|
+
slot_fillers: @slot_fillers,
|
|
38
|
+
context: @context,
|
|
39
|
+
confidence: @confidence,
|
|
40
|
+
filled_count: filled_count,
|
|
41
|
+
complete: complete?,
|
|
42
|
+
created_at: @created_at
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module FrameSemantics
|
|
8
|
+
module Runners
|
|
9
|
+
module FrameSemantics
|
|
10
|
+
def create_semantic_frame(name:, domain:, **)
|
|
11
|
+
frame = engine.create_frame(name: name, domain: domain)
|
|
12
|
+
Legion::Logging.debug "[frame_semantics] created frame name=#{name} domain=#{domain} id=#{frame.id[0..7]}"
|
|
13
|
+
{ frame_id: frame.id, name: frame.name, domain: frame.domain, created: true }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def define_frame_slot(frame_id:, name:, slot_type: :core, required: true, **)
|
|
17
|
+
frame = engine.define_slot(frame_id: frame_id, name: name, slot_type: slot_type, required: required)
|
|
18
|
+
if frame
|
|
19
|
+
Legion::Logging.debug "[frame_semantics] defined slot #{name} on frame #{frame_id[0..7]}"
|
|
20
|
+
{ defined: true, frame_id: frame_id, slot_name: name, slot_type: slot_type }
|
|
21
|
+
else
|
|
22
|
+
{ defined: false, reason: :frame_not_found }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def fill_frame_slot(frame_id:, slot_name:, filler:, **)
|
|
27
|
+
result = engine.fill_slot(frame_id: frame_id, slot_name: slot_name, filler: filler)
|
|
28
|
+
if result
|
|
29
|
+
Legion::Logging.debug "[frame_semantics] filled slot #{slot_name} on frame #{frame_id[0..7]}"
|
|
30
|
+
{ filled: true, frame_id: frame_id, slot_name: slot_name, filler: filler }
|
|
31
|
+
else
|
|
32
|
+
{ filled: false, reason: :slot_or_frame_not_found }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def instantiate_semantic_frame(frame_id:, context:, confidence: 0.7, **)
|
|
37
|
+
instance = engine.instantiate_frame(frame_id: frame_id, context: context, confidence: confidence)
|
|
38
|
+
if instance
|
|
39
|
+
Legion::Logging.debug "[frame_semantics] instantiated frame #{frame_id[0..7]} instance=#{instance.id[0..7]}"
|
|
40
|
+
{ instantiated: true, instance_id: instance.id, frame_id: frame_id,
|
|
41
|
+
filled_count: instance.filled_count }
|
|
42
|
+
else
|
|
43
|
+
{ instantiated: false, reason: :frame_not_found }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def add_frame_relation(frame_id:, relation:, target_frame_id:, **)
|
|
48
|
+
result = engine.add_frame_relation(frame_id: frame_id, relation: relation,
|
|
49
|
+
target_frame_id: target_frame_id)
|
|
50
|
+
if result
|
|
51
|
+
Legion::Logging.debug "[frame_semantics] added relation #{relation} #{frame_id[0..7]}->#{target_frame_id[0..7]}"
|
|
52
|
+
{ added: true, frame_id: frame_id, relation: relation, target_frame_id: target_frame_id }
|
|
53
|
+
else
|
|
54
|
+
{ added: false, reason: :invalid_frame_or_relation }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def activate_semantic_frame(frame_id:, **)
|
|
59
|
+
result = engine.activate_frame(frame_id: frame_id)
|
|
60
|
+
if result
|
|
61
|
+
Legion::Logging.debug "[frame_semantics] activated frame #{frame_id[0..7]}"
|
|
62
|
+
{ activated: true, frame_id: frame_id }
|
|
63
|
+
else
|
|
64
|
+
{ activated: false, reason: :frame_not_found }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def active_frames_report(**)
|
|
69
|
+
frames = engine.active_frames
|
|
70
|
+
Legion::Logging.debug "[frame_semantics] active_frames count=#{frames.size}"
|
|
71
|
+
{ frames: frames.map(&:to_h), count: frames.size }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def related_frames_report(frame_id:, **)
|
|
75
|
+
frames = engine.related_frames(frame_id: frame_id)
|
|
76
|
+
Legion::Logging.debug "[frame_semantics] related_frames frame=#{frame_id[0..7]} count=#{frames.size}"
|
|
77
|
+
{ frames: frames.map(&:to_h), count: frames.size }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def complete_frames_report(**)
|
|
81
|
+
frames = engine.complete_frames
|
|
82
|
+
Legion::Logging.debug "[frame_semantics] complete_frames count=#{frames.size}"
|
|
83
|
+
{ frames: frames.map(&:to_h), count: frames.size }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def update_frame_semantics(**)
|
|
87
|
+
engine.decay_all
|
|
88
|
+
engine.prune_inactive
|
|
89
|
+
Legion::Logging.debug '[frame_semantics] decay_all + prune_inactive complete'
|
|
90
|
+
{ updated: true, stats: engine.to_h }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def frame_semantics_stats(**)
|
|
94
|
+
engine.to_h
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def engine
|
|
100
|
+
@engine ||= Helpers::FrameEngine.new
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/language/frame_semantics/version'
|
|
4
|
+
require 'legion/extensions/agentic/language/frame_semantics/helpers/constants'
|
|
5
|
+
require 'legion/extensions/agentic/language/frame_semantics/helpers/frame'
|
|
6
|
+
require 'legion/extensions/agentic/language/frame_semantics/helpers/frame_instance'
|
|
7
|
+
require 'legion/extensions/agentic/language/frame_semantics/helpers/frame_engine'
|
|
8
|
+
require 'legion/extensions/agentic/language/frame_semantics/runners/frame_semantics'
|
|
9
|
+
require 'legion/extensions/agentic/language/frame_semantics/helpers/client'
|
|
10
|
+
|
|
11
|
+
module Legion
|
|
12
|
+
module Extensions
|
|
13
|
+
module Agentic
|
|
14
|
+
module Language
|
|
15
|
+
module FrameSemantics
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/agentic/language/grammar/helpers/constants'
|
|
4
|
+
require 'legion/extensions/agentic/language/grammar/helpers/construction'
|
|
5
|
+
require 'legion/extensions/agentic/language/grammar/helpers/construal'
|
|
6
|
+
require 'legion/extensions/agentic/language/grammar/helpers/grammar_engine'
|
|
7
|
+
require 'legion/extensions/agentic/language/grammar/runners/cognitive_grammar'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Agentic
|
|
12
|
+
module Language
|
|
13
|
+
module Grammar
|
|
14
|
+
class Client
|
|
15
|
+
include Runners::CognitiveGrammar
|
|
16
|
+
|
|
17
|
+
def initialize(**)
|
|
18
|
+
@engine = Helpers::GrammarEngine.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :engine
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module Grammar
|
|
8
|
+
module Helpers
|
|
9
|
+
module Constants
|
|
10
|
+
CONSTRUAL_OPERATIONS = %i[perspective prominence specificity scope dynamicity].freeze
|
|
11
|
+
PROMINENCE_TYPES = %i[figure ground].freeze
|
|
12
|
+
SPECIFICITY_LEVELS = %i[schematic intermediate detailed].freeze
|
|
13
|
+
SCOPE_LEVELS = %i[immediate local global].freeze
|
|
14
|
+
EXPRESSION_TYPES = %i[nominal relational clausal].freeze
|
|
15
|
+
|
|
16
|
+
ACTIVATION_LABELS = {
|
|
17
|
+
(0.8..) => :entrenched,
|
|
18
|
+
(0.6...0.8) => :conventional,
|
|
19
|
+
(0.4...0.6) => :familiar,
|
|
20
|
+
(0.2...0.4) => :novel,
|
|
21
|
+
(..0.2) => :ad_hoc
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
MAX_CONSTRUCTIONS = 200
|
|
25
|
+
MAX_CONSTRUALS = 500
|
|
26
|
+
MAX_HISTORY = 500
|
|
27
|
+
|
|
28
|
+
DEFAULT_ACTIVATION = 0.3
|
|
29
|
+
ACTIVATION_BOOST = 0.1
|
|
30
|
+
ACTIVATION_DECAY = 0.02
|
|
31
|
+
ENTRENCHMENT_THRESHOLD = 0.8
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Language
|
|
9
|
+
module Grammar
|
|
10
|
+
module Helpers
|
|
11
|
+
class Construal
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :scene, :perspective, :figure, :ground, :specificity,
|
|
15
|
+
:scope, :dynamicity, :construction_id, :created_at
|
|
16
|
+
|
|
17
|
+
def initialize(scene:, perspective:, figure:, ground:,
|
|
18
|
+
specificity: :intermediate, scope: :local,
|
|
19
|
+
dynamicity: 0.5, construction_id: nil)
|
|
20
|
+
@id = SecureRandom.uuid
|
|
21
|
+
@scene = scene
|
|
22
|
+
@perspective = perspective
|
|
23
|
+
@figure = figure
|
|
24
|
+
@ground = ground
|
|
25
|
+
@specificity = specificity.to_sym
|
|
26
|
+
@scope = scope.to_sym
|
|
27
|
+
@dynamicity = dynamicity.clamp(0.0, 1.0)
|
|
28
|
+
@construction_id = construction_id
|
|
29
|
+
@created_at = Time.now.utc
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def prominent_element
|
|
33
|
+
@figure
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def background_element
|
|
37
|
+
@ground
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def detailed?
|
|
41
|
+
@specificity == :detailed
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def global_scope?
|
|
45
|
+
@scope == :global
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_h
|
|
49
|
+
{
|
|
50
|
+
id: @id,
|
|
51
|
+
scene: @scene,
|
|
52
|
+
perspective: @perspective,
|
|
53
|
+
figure: @figure,
|
|
54
|
+
ground: @ground,
|
|
55
|
+
specificity: @specificity,
|
|
56
|
+
scope: @scope,
|
|
57
|
+
dynamicity: @dynamicity,
|
|
58
|
+
construction_id: @construction_id,
|
|
59
|
+
created_at: @created_at
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Agentic
|
|
8
|
+
module Language
|
|
9
|
+
module Grammar
|
|
10
|
+
module Helpers
|
|
11
|
+
class Construction
|
|
12
|
+
include Constants
|
|
13
|
+
|
|
14
|
+
attr_reader :id, :form, :meaning, :expression_type, :usage_count, :domain, :created_at
|
|
15
|
+
attr_accessor :activation
|
|
16
|
+
|
|
17
|
+
def initialize(form:, meaning:, expression_type:, domain:, activation: DEFAULT_ACTIVATION)
|
|
18
|
+
@id = SecureRandom.uuid
|
|
19
|
+
@form = form
|
|
20
|
+
@meaning = meaning
|
|
21
|
+
@expression_type = expression_type.to_sym
|
|
22
|
+
@activation = activation.clamp(0.0, 1.0)
|
|
23
|
+
@usage_count = 0
|
|
24
|
+
@domain = domain
|
|
25
|
+
@created_at = Time.now.utc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def use!
|
|
29
|
+
@usage_count += 1
|
|
30
|
+
@activation = [@activation + ACTIVATION_BOOST, 1.0].min.round(10)
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def decay!
|
|
35
|
+
@activation = [@activation - ACTIVATION_DECAY, 0.0].max
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def entrenched?
|
|
40
|
+
@activation >= ENTRENCHMENT_THRESHOLD
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def activation_label
|
|
44
|
+
match = ACTIVATION_LABELS.find { |range, _| range.cover?(@activation) }
|
|
45
|
+
match ? match.last : :ad_hoc
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_h
|
|
49
|
+
{
|
|
50
|
+
id: @id,
|
|
51
|
+
form: @form,
|
|
52
|
+
meaning: @meaning,
|
|
53
|
+
expression_type: @expression_type,
|
|
54
|
+
activation: @activation,
|
|
55
|
+
usage_count: @usage_count,
|
|
56
|
+
domain: @domain,
|
|
57
|
+
entrenched: entrenched?,
|
|
58
|
+
activation_label: activation_label,
|
|
59
|
+
created_at: @created_at
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Agentic
|
|
6
|
+
module Language
|
|
7
|
+
module Grammar
|
|
8
|
+
module Helpers
|
|
9
|
+
class GrammarEngine
|
|
10
|
+
include Constants
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@constructions = {}
|
|
14
|
+
@construals = {}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_construction(form:, meaning:, expression_type:, domain:, activation: DEFAULT_ACTIVATION)
|
|
18
|
+
prune_constructions_if_needed
|
|
19
|
+
construction = Construction.new(
|
|
20
|
+
form: form,
|
|
21
|
+
meaning: meaning,
|
|
22
|
+
expression_type: expression_type,
|
|
23
|
+
domain: domain,
|
|
24
|
+
activation: activation
|
|
25
|
+
)
|
|
26
|
+
@constructions[construction.id] = construction
|
|
27
|
+
construction
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create_construal(scene:, perspective:, figure:, ground:,
|
|
31
|
+
specificity: :intermediate, scope: :local,
|
|
32
|
+
dynamicity: 0.5, construction_id: nil)
|
|
33
|
+
prune_construals_if_needed
|
|
34
|
+
construal = Construal.new(
|
|
35
|
+
scene: scene,
|
|
36
|
+
perspective: perspective,
|
|
37
|
+
figure: figure,
|
|
38
|
+
ground: ground,
|
|
39
|
+
specificity: specificity,
|
|
40
|
+
scope: scope,
|
|
41
|
+
dynamicity: dynamicity,
|
|
42
|
+
construction_id: construction_id
|
|
43
|
+
)
|
|
44
|
+
@construals[construal.id] = construal
|
|
45
|
+
construal
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def use_construction(construction_id:)
|
|
49
|
+
construction = @constructions[construction_id]
|
|
50
|
+
return nil unless construction
|
|
51
|
+
|
|
52
|
+
construction.use!
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def construals_for_scene(scene:)
|
|
56
|
+
@construals.values.select { |c| c.scene == scene }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def entrenched_constructions
|
|
60
|
+
@constructions.values.select(&:entrenched?)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def constructions_by_domain(domain:)
|
|
64
|
+
@constructions.values.select { |c| c.domain == domain }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def constructions_by_type(expression_type:)
|
|
68
|
+
type = expression_type.to_sym
|
|
69
|
+
@constructions.values.select { |c| c.expression_type == type }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def most_used(limit: 5)
|
|
73
|
+
@constructions.values.sort_by { |c| -c.usage_count }.first(limit)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def most_activated(limit: 5)
|
|
77
|
+
@constructions.values.sort_by { |c| -c.activation }.first(limit)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def decay_all
|
|
81
|
+
@constructions.each_value(&:decay!)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def prune_inactive
|
|
85
|
+
before = @constructions.size
|
|
86
|
+
@constructions.delete_if { |_, c| c.activation <= 0.05 }
|
|
87
|
+
before - @constructions.size
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def to_h
|
|
91
|
+
{
|
|
92
|
+
constructions_count: @constructions.size,
|
|
93
|
+
construals_count: @construals.size,
|
|
94
|
+
entrenched_count: entrenched_constructions.size
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def prune_constructions_if_needed
|
|
101
|
+
return if @constructions.size < MAX_CONSTRUCTIONS
|
|
102
|
+
|
|
103
|
+
oldest = @constructions.values.min_by(&:activation)
|
|
104
|
+
@constructions.delete(oldest.id) if oldest
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def prune_construals_if_needed
|
|
108
|
+
return if @construals.size < MAX_CONSTRUALS
|
|
109
|
+
|
|
110
|
+
oldest = @construals.values.min_by(&:created_at)
|
|
111
|
+
@construals.delete(oldest.id) if oldest
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|