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,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
|
data/lib/legion/extensions/agentic/language/conceptual_metaphor/runners/conceptual_metaphor.rb
ADDED
|
@@ -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,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
|