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,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Agentic
8
+ module Language
9
+ module ConceptualMetaphor
10
+ module Helpers
11
+ class Metaphor
12
+ include Constants
13
+
14
+ attr_reader :id, :source_domain, :target_domain, :metaphor_type,
15
+ :mappings, :entailments, :strength, :conventionality,
16
+ :use_count, :created_at, :last_used_at
17
+
18
+ def initialize(source_domain:, target_domain:, metaphor_type:,
19
+ mappings:, strength: nil, conventionality: nil)
20
+ @id = SecureRandom.uuid
21
+ @source_domain = source_domain
22
+ @target_domain = target_domain
23
+ @metaphor_type = metaphor_type
24
+ @mappings = mappings
25
+ @entailments = []
26
+ @strength = (strength || DEFAULT_STRENGTH).to_f.clamp(STRENGTH_FLOOR, STRENGTH_CEILING)
27
+ @conventionality = (conventionality || DEFAULT_STRENGTH).to_f.clamp(STRENGTH_FLOOR, STRENGTH_CEILING)
28
+ @use_count = 0
29
+ @created_at = Time.now.utc
30
+ @last_used_at = @created_at
31
+ end
32
+
33
+ def use!
34
+ @use_count += 1
35
+ @last_used_at = Time.now.utc
36
+ @strength = (@strength + REINFORCEMENT_BOOST).clamp(STRENGTH_FLOOR, STRENGTH_CEILING)
37
+ increase_conventionality
38
+ end
39
+
40
+ def add_entailment(entailment)
41
+ @entailments << entailment
42
+ end
43
+
44
+ def map_concept(source_concept)
45
+ @mappings[source_concept]
46
+ end
47
+
48
+ def coverage
49
+ return 0.0 if @mappings.empty?
50
+
51
+ @mappings.values.compact.size.to_f / @mappings.size
52
+ end
53
+
54
+ def conventional?
55
+ @conventionality >= CONVENTIONALITY_THRESHOLD
56
+ end
57
+
58
+ def novel?
59
+ @conventionality <= NOVELTY_THRESHOLD
60
+ end
61
+
62
+ def conventionality_label
63
+ CONVENTIONALITY_LABELS.find { |range, _| range.cover?(@conventionality) }&.last || :unknown
64
+ end
65
+
66
+ def strength_label
67
+ STRENGTH_LABELS.find { |range, _| range.cover?(@strength) }&.last || :unknown
68
+ end
69
+
70
+ def decay!
71
+ @strength = (@strength - DECAY_RATE).clamp(STRENGTH_FLOOR, STRENGTH_CEILING)
72
+ end
73
+
74
+ def stale?
75
+ (Time.now.utc - @last_used_at) > STALE_THRESHOLD
76
+ end
77
+
78
+ def to_h
79
+ {
80
+ id: @id,
81
+ source_domain: @source_domain,
82
+ target_domain: @target_domain,
83
+ metaphor_type: @metaphor_type,
84
+ mappings: @mappings,
85
+ entailments: @entailments,
86
+ strength: @strength,
87
+ conventionality: @conventionality,
88
+ conventionality_label: conventionality_label,
89
+ strength_label: strength_label,
90
+ use_count: @use_count,
91
+ coverage: coverage,
92
+ created_at: @created_at,
93
+ last_used_at: @last_used_at
94
+ }
95
+ end
96
+
97
+ private
98
+
99
+ def increase_conventionality
100
+ increment = REINFORCEMENT_BOOST * 0.5
101
+ @conventionality = (@conventionality + increment).clamp(STRENGTH_FLOOR, STRENGTH_CEILING)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Language
7
+ module ConceptualMetaphor
8
+ module Helpers
9
+ class MetaphorEngine
10
+ include Constants
11
+
12
+ attr_reader :history
13
+
14
+ def initialize
15
+ @metaphors = {}
16
+ @domains = Set.new
17
+ @history = []
18
+ end
19
+
20
+ def create_metaphor(source_domain:, target_domain:, metaphor_type:,
21
+ mappings:, strength: nil, conventionality: nil)
22
+ evict_oldest if @metaphors.size >= MAX_METAPHORS
23
+
24
+ return { success: false, reason: :invalid_metaphor_type } unless METAPHOR_TYPES.include?(metaphor_type)
25
+
26
+ metaphor = Metaphor.new(
27
+ source_domain: source_domain,
28
+ target_domain: target_domain,
29
+ metaphor_type: metaphor_type,
30
+ mappings: mappings,
31
+ strength: strength,
32
+ conventionality: conventionality
33
+ )
34
+
35
+ @metaphors[metaphor.id] = metaphor
36
+ register_domain(source_domain)
37
+ register_domain(target_domain)
38
+ record_history(:created, metaphor.id)
39
+ metaphor
40
+ end
41
+
42
+ def apply_metaphor(metaphor_id:, source_concept:)
43
+ metaphor = @metaphors[metaphor_id]
44
+ return { found: false } unless metaphor
45
+
46
+ target = metaphor.map_concept(source_concept)
47
+ return { found: true, mapped: false } unless target
48
+
49
+ metaphor.use!
50
+ record_history(:applied, metaphor_id)
51
+ build_apply_result(metaphor, source_concept, target)
52
+ end
53
+
54
+ def add_entailment(metaphor_id:, entailment:)
55
+ metaphor = @metaphors[metaphor_id]
56
+ return { success: false, reason: :not_found } unless metaphor
57
+
58
+ metaphor.add_entailment(entailment)
59
+ record_history(:entailment_added, metaphor_id)
60
+ { success: true, metaphor_id: metaphor_id, entailment_count: metaphor.entailments.size }
61
+ end
62
+
63
+ def find_by_target(target_domain:)
64
+ @metaphors.values.select { |m| m.target_domain == target_domain }
65
+ end
66
+
67
+ def find_by_source(source_domain:)
68
+ @metaphors.values.select { |m| m.source_domain == source_domain }
69
+ end
70
+
71
+ def find_by_domain(domain:)
72
+ @metaphors.values.select do |m|
73
+ m.source_domain == domain || m.target_domain == domain
74
+ end
75
+ end
76
+
77
+ def conventional_metaphors
78
+ @metaphors.values.select(&:conventional?)
79
+ end
80
+
81
+ def novel_metaphors
82
+ @metaphors.values.select(&:novel?)
83
+ end
84
+
85
+ def strongest(limit: 5)
86
+ @metaphors.values.sort_by { |m| -m.strength }.first(limit)
87
+ end
88
+
89
+ def by_type(metaphor_type:)
90
+ @metaphors.values.select { |m| m.metaphor_type == metaphor_type }
91
+ end
92
+
93
+ def decay_all
94
+ @metaphors.each_value(&:decay!)
95
+ end
96
+
97
+ def prune_weak
98
+ weak_ids = @metaphors.select { |_id, m| m.strength <= 0.05 }.keys
99
+ weak_ids.each { |id| @metaphors.delete(id) }
100
+ weak_ids.size
101
+ end
102
+
103
+ def to_h
104
+ {
105
+ total_metaphors: @metaphors.size,
106
+ total_domains: @domains.size,
107
+ conventional_count: conventional_metaphors.size,
108
+ novel_count: novel_metaphors.size,
109
+ history_count: @history.size,
110
+ domains: @domains.to_a,
111
+ type_counts: type_counts
112
+ }
113
+ end
114
+
115
+ private
116
+
117
+ def build_apply_result(metaphor, source_concept, target)
118
+ {
119
+ found: true,
120
+ mapped: true,
121
+ source_concept: source_concept,
122
+ target_concept: target,
123
+ strength: metaphor.strength,
124
+ metaphor_id: metaphor.id
125
+ }
126
+ end
127
+
128
+ def register_domain(domain)
129
+ @domains.add(domain)
130
+ @domains.delete(@domains.first) if @domains.size > MAX_DOMAINS
131
+ end
132
+
133
+ def evict_oldest
134
+ oldest_id = @metaphors.min_by { |_id, m| m.last_used_at }&.first
135
+ @metaphors.delete(oldest_id) if oldest_id
136
+ end
137
+
138
+ def record_history(event, metaphor_id)
139
+ @history << { event: event, metaphor_id: metaphor_id, at: Time.now.utc }
140
+ @history.shift while @history.size > MAX_HISTORY
141
+ end
142
+
143
+ def type_counts
144
+ @metaphors.values.each_with_object(Hash.new(0)) do |m, counts|
145
+ counts[m.metaphor_type] += 1
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Agentic
6
+ module Language
7
+ module ConceptualMetaphor
8
+ module Runners
9
+ module ConceptualMetaphor
10
+ include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
11
+ Legion::Extensions::Helpers.const_defined?(:Lex)
12
+
13
+ def create_metaphor(source_domain:, target_domain:, metaphor_type:,
14
+ mappings:, strength: nil, conventionality: nil, **)
15
+ unless Helpers::Constants::METAPHOR_TYPES.include?(metaphor_type)
16
+ return { success: false, error: :invalid_metaphor_type,
17
+ valid_types: Helpers::Constants::METAPHOR_TYPES }
18
+ end
19
+
20
+ result = engine.create_metaphor(
21
+ source_domain: source_domain,
22
+ target_domain: target_domain,
23
+ metaphor_type: metaphor_type,
24
+ mappings: mappings,
25
+ strength: strength,
26
+ conventionality: conventionality
27
+ )
28
+
29
+ return result unless result.is_a?(Helpers::Metaphor)
30
+
31
+ Legion::Logging.debug "[conceptual_metaphor] created #{source_domain}->#{target_domain} " \
32
+ "type=#{metaphor_type} id=#{result.id[0..7]}"
33
+ { success: true, metaphor_id: result.id, source_domain: source_domain,
34
+ target_domain: target_domain, metaphor_type: metaphor_type,
35
+ strength: result.strength, conventionality: result.conventionality }
36
+ end
37
+
38
+ def apply_metaphor(metaphor_id:, source_concept:, **)
39
+ result = engine.apply_metaphor(metaphor_id: metaphor_id, source_concept: source_concept)
40
+ Legion::Logging.debug "[conceptual_metaphor] apply id=#{metaphor_id[0..7]} " \
41
+ "concept=#{source_concept} mapped=#{result[:mapped]}"
42
+ { success: true }.merge(result)
43
+ end
44
+
45
+ def add_metaphor_entailment(metaphor_id:, entailment:, **)
46
+ result = engine.add_entailment(metaphor_id: metaphor_id, entailment: entailment)
47
+ Legion::Logging.debug "[conceptual_metaphor] entailment id=#{metaphor_id[0..7]} " \
48
+ "success=#{result[:success]}"
49
+ result
50
+ end
51
+
52
+ def find_metaphors_for(domain:, **)
53
+ metaphors = engine.find_by_domain(domain: domain)
54
+ Legion::Logging.debug "[conceptual_metaphor] find domain=#{domain} count=#{metaphors.size}"
55
+ { success: true, domain: domain, metaphors: metaphors.map(&:to_h), count: metaphors.size }
56
+ end
57
+
58
+ def conventional_metaphors(**)
59
+ metaphors = engine.conventional_metaphors
60
+ Legion::Logging.debug "[conceptual_metaphor] conventional count=#{metaphors.size}"
61
+ { success: true, metaphors: metaphors.map(&:to_h), count: metaphors.size }
62
+ end
63
+
64
+ def novel_metaphors(**)
65
+ metaphors = engine.novel_metaphors
66
+ Legion::Logging.debug "[conceptual_metaphor] novel count=#{metaphors.size}"
67
+ { success: true, metaphors: metaphors.map(&:to_h), count: metaphors.size }
68
+ end
69
+
70
+ def strongest_metaphors(limit: 5, **)
71
+ metaphors = engine.strongest(limit: limit)
72
+ Legion::Logging.debug "[conceptual_metaphor] strongest limit=#{limit} count=#{metaphors.size}"
73
+ { success: true, metaphors: metaphors.map(&:to_h), count: metaphors.size }
74
+ end
75
+
76
+ def metaphors_by_type(metaphor_type:, **)
77
+ metaphors = engine.by_type(metaphor_type: metaphor_type)
78
+ Legion::Logging.debug "[conceptual_metaphor] by_type=#{metaphor_type} count=#{metaphors.size}"
79
+ { success: true, metaphor_type: metaphor_type, metaphors: metaphors.map(&:to_h),
80
+ count: metaphors.size }
81
+ end
82
+
83
+ def update_conceptual_metaphor(**)
84
+ engine.decay_all
85
+ pruned = engine.prune_weak
86
+ Legion::Logging.debug "[conceptual_metaphor] decay+prune pruned=#{pruned}"
87
+ { success: true, pruned: pruned }
88
+ end
89
+
90
+ def conceptual_metaphor_stats(**)
91
+ stats = engine.to_h
92
+ Legion::Logging.debug "[conceptual_metaphor] stats total=#{stats[:total_metaphors]}"
93
+ { success: true }.merge(stats)
94
+ end
95
+
96
+ private
97
+
98
+ def engine
99
+ @engine ||= Helpers::MetaphorEngine.new
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ 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 ConceptualMetaphor
8
+ VERSION = '0.1.0'
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/agentic/language/conceptual_metaphor/version'
4
+ require 'legion/extensions/agentic/language/conceptual_metaphor/helpers/constants'
5
+ require 'legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor'
6
+ require 'legion/extensions/agentic/language/conceptual_metaphor/helpers/metaphor_engine'
7
+ require 'legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor'
8
+ require 'legion/extensions/agentic/language/conceptual_metaphor/client'
9
+
10
+ module Legion
11
+ module Extensions
12
+ module Agentic
13
+ module Language
14
+ module ConceptualMetaphor
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
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 Client
10
+ include Runners::FrameSemantics
11
+
12
+ private
13
+
14
+ def engine
15
+ @engine ||= FrameEngine.new
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
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
+ SLOT_TYPES = %i[core peripheral extra_thematic].freeze
10
+ FRAME_RELATIONS = %i[inherits_from is_inherited_by uses is_used_by subframe_of has_subframe].freeze
11
+ ACTIVATION_LABELS = {
12
+ (0.8..) => :dominant,
13
+ (0.6...0.8) => :active,
14
+ (0.4...0.6) => :primed,
15
+ (0.2...0.4) => :latent,
16
+ (..0.2) => :inactive
17
+ }.freeze
18
+
19
+ MAX_FRAMES = 150
20
+ MAX_INSTANCES = 500
21
+ MAX_HISTORY = 500
22
+ DEFAULT_ACTIVATION = 0.3
23
+ ACTIVATION_BOOST = 0.15
24
+ ACTIVATION_DECAY = 0.03
25
+ SLOT_FILL_BOOST = 0.1
26
+ COMPLETION_THRESHOLD = 0.7
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,109 @@
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 Frame
12
+ attr_reader :id, :name, :domain, :slots, :relations, :activation, :activation_count, :created_at
13
+
14
+ def initialize(name:, domain:)
15
+ @id = SecureRandom.uuid
16
+ @name = name
17
+ @domain = domain
18
+ @slots = {}
19
+ @relations = []
20
+ @activation = DEFAULT_ACTIVATION
21
+ @activation_count = 0
22
+ @created_at = Time.now.utc
23
+ end
24
+
25
+ def add_slot(name:, slot_type: :core, required: true)
26
+ @slots[name] = { type: slot_type, filler: nil, required: required }
27
+ self
28
+ end
29
+
30
+ def fill_slot(name:, filler:)
31
+ return false unless @slots.key?(name)
32
+
33
+ @slots[name][:filler] = filler
34
+ @activation = [@activation + SLOT_FILL_BOOST, 1.0].min
35
+ true
36
+ end
37
+
38
+ def clear_slot(name:)
39
+ return false unless @slots.key?(name)
40
+
41
+ @slots[name][:filler] = nil
42
+ true
43
+ end
44
+
45
+ def core_slots
46
+ @slots.select { |_k, v| v[:type] == :core }
47
+ end
48
+
49
+ def filled_slots
50
+ @slots.reject { |_k, v| v[:filler].nil? }
51
+ end
52
+
53
+ def completion_ratio
54
+ cs = core_slots
55
+ return 0.0 if cs.empty?
56
+
57
+ filled_core = cs.count { |_k, v| !v[:filler].nil? }
58
+ filled_core.to_f / cs.size
59
+ end
60
+
61
+ def complete?
62
+ completion_ratio >= COMPLETION_THRESHOLD
63
+ end
64
+
65
+ def activate!
66
+ @activation = [@activation + ACTIVATION_BOOST, 1.0].min
67
+ @activation_count += 1
68
+ self
69
+ end
70
+
71
+ def decay!
72
+ @activation = [@activation - ACTIVATION_DECAY, 0.0].max
73
+ self
74
+ end
75
+
76
+ def activation_label
77
+ ACTIVATION_LABELS.each do |range, label|
78
+ return label if range.cover?(@activation)
79
+ end
80
+ :inactive
81
+ end
82
+
83
+ def add_relation(relation:, target_frame_id:)
84
+ @relations << { relation: relation, target_frame_id: target_frame_id }
85
+ self
86
+ end
87
+
88
+ def to_h
89
+ {
90
+ id: @id,
91
+ name: @name,
92
+ domain: @domain,
93
+ slots: @slots,
94
+ relations: @relations,
95
+ activation: @activation,
96
+ activation_label: activation_label,
97
+ activation_count: @activation_count,
98
+ completion_ratio: completion_ratio,
99
+ complete: complete?,
100
+ created_at: @created_at
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end