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.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +21 -0
  5. data/README.md +13 -0
  6. data/lex-agentic-language.gemspec +30 -0
  7. data/lib/legion/extensions/agentic/language/conceptual_blending/client.rb +25 -0
  8. data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/blend.rb +91 -0
  9. data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/blending_engine.rb +171 -0
  10. data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/constants.rb +35 -0
  11. data/lib/legion/extensions/agentic/language/conceptual_blending/helpers/mental_space.rb +51 -0
  12. data/lib/legion/extensions/agentic/language/conceptual_blending/runners/conceptual_blending.rb +106 -0
  13. data/lib/legion/extensions/agentic/language/conceptual_blending/version.rb +13 -0
  14. data/lib/legion/extensions/agentic/language/conceptual_blending.rb +20 -0
  15. data/lib/legion/extensions/agentic/language/conceptual_metaphor/client.rb +19 -0
  16. data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/constants.rb +49 -0
  17. data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor.rb +109 -0
  18. data/lib/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_engine.rb +154 -0
  19. data/lib/legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor.rb +107 -0
  20. data/lib/legion/extensions/agentic/language/conceptual_metaphor/version.rb +13 -0
  21. data/lib/legion/extensions/agentic/language/conceptual_metaphor.rb +19 -0
  22. data/lib/legion/extensions/agentic/language/frame_semantics/helpers/client.rb +23 -0
  23. data/lib/legion/extensions/agentic/language/frame_semantics/helpers/constants.rb +32 -0
  24. data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame.rb +109 -0
  25. data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame_engine.rb +139 -0
  26. data/lib/legion/extensions/agentic/language/frame_semantics/helpers/frame_instance.rb +51 -0
  27. data/lib/legion/extensions/agentic/language/frame_semantics/runners/frame_semantics.rb +108 -0
  28. data/lib/legion/extensions/agentic/language/frame_semantics/version.rb +13 -0
  29. data/lib/legion/extensions/agentic/language/frame_semantics.rb +20 -0
  30. data/lib/legion/extensions/agentic/language/grammar/client.rb +29 -0
  31. data/lib/legion/extensions/agentic/language/grammar/helpers/constants.rb +38 -0
  32. data/lib/legion/extensions/agentic/language/grammar/helpers/construal.rb +68 -0
  33. data/lib/legion/extensions/agentic/language/grammar/helpers/construction.rb +68 -0
  34. data/lib/legion/extensions/agentic/language/grammar/helpers/grammar_engine.rb +119 -0
  35. data/lib/legion/extensions/agentic/language/grammar/runners/cognitive_grammar.rb +100 -0
  36. data/lib/legion/extensions/agentic/language/grammar/version.rb +13 -0
  37. data/lib/legion/extensions/agentic/language/grammar.rb +20 -0
  38. data/lib/legion/extensions/agentic/language/inner_speech/client.rb +19 -0
  39. data/lib/legion/extensions/agentic/language/inner_speech/helpers/constants.rb +53 -0
  40. data/lib/legion/extensions/agentic/language/inner_speech/helpers/inner_voice.rb +141 -0
  41. data/lib/legion/extensions/agentic/language/inner_speech/helpers/speech_stream.rb +128 -0
  42. data/lib/legion/extensions/agentic/language/inner_speech/helpers/utterance.rb +90 -0
  43. data/lib/legion/extensions/agentic/language/inner_speech/runners/inner_speech.rb +87 -0
  44. data/lib/legion/extensions/agentic/language/inner_speech/version.rb +13 -0
  45. data/lib/legion/extensions/agentic/language/inner_speech.rb +20 -0
  46. data/lib/legion/extensions/agentic/language/language/client.rb +26 -0
  47. data/lib/legion/extensions/agentic/language/language/helpers/constants.rb +43 -0
  48. data/lib/legion/extensions/agentic/language/language/helpers/lexicon.rb +63 -0
  49. data/lib/legion/extensions/agentic/language/language/helpers/summarizer.rb +167 -0
  50. data/lib/legion/extensions/agentic/language/language/runners/language.rb +134 -0
  51. data/lib/legion/extensions/agentic/language/language/version.rb +13 -0
  52. data/lib/legion/extensions/agentic/language/language.rb +19 -0
  53. data/lib/legion/extensions/agentic/language/narrative_reasoning/client.rb +28 -0
  54. data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative.rb +123 -0
  55. data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_engine.rb +122 -0
  56. data/lib/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_event.rb +41 -0
  57. data/lib/legion/extensions/agentic/language/narrative_reasoning/runners/narrative_reasoning.rb +122 -0
  58. data/lib/legion/extensions/agentic/language/narrative_reasoning/version.rb +13 -0
  59. data/lib/legion/extensions/agentic/language/narrative_reasoning.rb +18 -0
  60. data/lib/legion/extensions/agentic/language/narrator/client.rb +27 -0
  61. data/lib/legion/extensions/agentic/language/narrator/helpers/constants.rb +69 -0
  62. data/lib/legion/extensions/agentic/language/narrator/helpers/journal.rb +68 -0
  63. data/lib/legion/extensions/agentic/language/narrator/helpers/llm_enhancer.rb +105 -0
  64. data/lib/legion/extensions/agentic/language/narrator/helpers/prose.rb +122 -0
  65. data/lib/legion/extensions/agentic/language/narrator/helpers/synthesizer.rb +138 -0
  66. data/lib/legion/extensions/agentic/language/narrator/runners/narrator.rb +196 -0
  67. data/lib/legion/extensions/agentic/language/narrator/version.rb +13 -0
  68. data/lib/legion/extensions/agentic/language/narrator.rb +21 -0
  69. data/lib/legion/extensions/agentic/language/pragmatic_inference/client.rb +28 -0
  70. data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/constants.rb +52 -0
  71. data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/pragmatic_engine.rb +164 -0
  72. data/lib/legion/extensions/agentic/language/pragmatic_inference/helpers/utterance.rb +84 -0
  73. data/lib/legion/extensions/agentic/language/pragmatic_inference/runners/pragmatic_inference.rb +136 -0
  74. data/lib/legion/extensions/agentic/language/pragmatic_inference/version.rb +13 -0
  75. data/lib/legion/extensions/agentic/language/pragmatic_inference.rb +18 -0
  76. data/lib/legion/extensions/agentic/language/version.rb +11 -0
  77. data/lib/legion/extensions/agentic/language.rb +28 -0
  78. data/spec/legion/extensions/agentic/language/conceptual_blending/client_spec.rb +78 -0
  79. data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/blend_spec.rb +141 -0
  80. data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/blending_engine_spec.rb +211 -0
  81. data/spec/legion/extensions/agentic/language/conceptual_blending/helpers/mental_space_spec.rb +85 -0
  82. data/spec/legion/extensions/agentic/language/conceptual_blending/runners/conceptual_blending_spec.rb +162 -0
  83. data/spec/legion/extensions/agentic/language/conceptual_metaphor/client_spec.rb +29 -0
  84. data/spec/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_engine_spec.rb +166 -0
  85. data/spec/legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_spec.rb +133 -0
  86. data/spec/legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor_spec.rb +133 -0
  87. data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_engine_spec.rb +227 -0
  88. data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_instance_spec.rb +83 -0
  89. data/spec/legion/extensions/agentic/language/frame_semantics/helpers/frame_spec.rb +213 -0
  90. data/spec/legion/extensions/agentic/language/frame_semantics/runners/frame_semantics_spec.rb +155 -0
  91. data/spec/legion/extensions/agentic/language/grammar/client_spec.rb +121 -0
  92. data/spec/legion/extensions/agentic/language/grammar/cognitive_grammar_spec.rb +18 -0
  93. data/spec/legion/extensions/agentic/language/grammar/helpers/constants_spec.rb +67 -0
  94. data/spec/legion/extensions/agentic/language/grammar/helpers/construal_spec.rb +124 -0
  95. data/spec/legion/extensions/agentic/language/grammar/helpers/construction_spec.rb +155 -0
  96. data/spec/legion/extensions/agentic/language/grammar/helpers/grammar_engine_spec.rb +206 -0
  97. data/spec/legion/extensions/agentic/language/grammar/runners/cognitive_grammar_spec.rb +189 -0
  98. data/spec/legion/extensions/agentic/language/inner_speech/client_spec.rb +39 -0
  99. data/spec/legion/extensions/agentic/language/inner_speech/helpers/inner_voice_spec.rb +185 -0
  100. data/spec/legion/extensions/agentic/language/inner_speech/helpers/speech_stream_spec.rb +158 -0
  101. data/spec/legion/extensions/agentic/language/inner_speech/helpers/utterance_spec.rb +121 -0
  102. data/spec/legion/extensions/agentic/language/inner_speech/runners/inner_speech_spec.rb +102 -0
  103. data/spec/legion/extensions/agentic/language/language/client_spec.rb +20 -0
  104. data/spec/legion/extensions/agentic/language/language/helpers/constants_spec.rb +31 -0
  105. data/spec/legion/extensions/agentic/language/language/helpers/lexicon_spec.rb +116 -0
  106. data/spec/legion/extensions/agentic/language/language/helpers/summarizer_spec.rb +224 -0
  107. data/spec/legion/extensions/agentic/language/language/runners/language_spec.rb +169 -0
  108. data/spec/legion/extensions/agentic/language/narrative_reasoning/client_spec.rb +19 -0
  109. data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_engine_spec.rb +182 -0
  110. data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_event_spec.rb +61 -0
  111. data/spec/legion/extensions/agentic/language/narrative_reasoning/helpers/narrative_spec.rb +168 -0
  112. data/spec/legion/extensions/agentic/language/narrative_reasoning/runners/narrative_reasoning_spec.rb +174 -0
  113. data/spec/legion/extensions/agentic/language/narrator/client_spec.rb +24 -0
  114. data/spec/legion/extensions/agentic/language/narrator/helpers/journal_spec.rb +95 -0
  115. data/spec/legion/extensions/agentic/language/narrator/helpers/llm_enhancer_spec.rb +107 -0
  116. data/spec/legion/extensions/agentic/language/narrator/helpers/prose_spec.rb +134 -0
  117. data/spec/legion/extensions/agentic/language/narrator/helpers/synthesizer_spec.rb +89 -0
  118. data/spec/legion/extensions/agentic/language/narrator/runners/narrator_llm_spec.rb +74 -0
  119. data/spec/legion/extensions/agentic/language/narrator/runners/narrator_spec.rb +126 -0
  120. data/spec/legion/extensions/agentic/language/pragmatic_inference/client_spec.rb +19 -0
  121. data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/constants_spec.rb +73 -0
  122. data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/pragmatic_engine_spec.rb +185 -0
  123. data/spec/legion/extensions/agentic/language/pragmatic_inference/helpers/utterance_spec.rb +111 -0
  124. data/spec/legion/extensions/agentic/language/pragmatic_inference/runners/pragmatic_inference_spec.rb +231 -0
  125. data/spec/spec_helper.rb +33 -0
  126. 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Language
7
+ module FrameSemantics
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ 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