Module: Legion::Extensions::Agentic::Language::Language::Helpers::Summarizer

Defined in:
lib/legion/extensions/agentic/language/language/helpers/summarizer.rb

Class Method Summary collapse

Class Method Details

.classify_knowledge(count) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 83

def classify_knowledge(count)
  if count >= Constants::KNOWLEDGE_RICH then :rich
  elsif count >= Constants::KNOWLEDGE_MODERATE then :moderate
  elsif count >= Constants::KNOWLEDGE_SPARSE   then :sparse
  else :none
  end
end

.emotional_tone(traces) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 102

def emotional_tone(traces)
  valences = traces.map { |t| t[:emotional_valence] || 0.0 }
  intensities = traces.map { |t| t[:emotional_intensity] || 0.0 }

  avg_valence = valences.sum / valences.size
  avg_intensity = intensities.sum / intensities.size

  {
    avg_valence:   avg_valence.round(3),
    avg_intensity: avg_intensity.round(3),
    tone:          tone_label(avg_valence, avg_intensity)
  }
end

.empty_summary(domain) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 145

def empty_summary(domain)
  {
    domain:          domain,
    knowledge_level: :none,
    trace_count:     0,
    type_breakdown:  {},
    key_facts:       [],
    strength_stats:  { mean: 0.0, max: 0.0, min: 0.0, strong: 0, weak: 0 },
    emotional_tone:  { avg_valence: 0.0, avg_intensity: 0.0, tone: :neutral },
    freshness:       { avg_age_seconds: 0.0, freshest: 0.0, stalest: 0.0, label: :stale }
  }
end

.extract_content_text(payload) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 74

def extract_content_text(payload)
  case payload
  when String then payload
  when Hash   then payload[:text] || payload[:content] || payload[:summary] || payload.to_s
  when Array  then payload.first.to_s
  else payload.to_s
  end
end

.extract_key_facts(grouped, depth: :standard) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 41

def extract_key_facts(grouped, depth: :standard)
  return nil unless Constants::DEPTHS.include?(depth.to_sym)

  limit = case depth
          when :brief    then 3
          when :detailed then 15
          else 7
          end

  facts = []
  grouped.each do |type, traces|
    sorted = traces.sort_by { |t| -(t[:strength] || 0) }
    count = [sorted.size, limit_per_type(type, limit)].min
    sorted.first(count).each do |trace|
      facts << format_fact(trace, type)
    end
  end

  facts.first(limit)
end

.format_fact(trace, type) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 62

def format_fact(trace, type)
  content = extract_content_text(trace[:content_payload])
  {
    trace_id:    trace[:trace_id],
    type:        type,
    content:     content,
    strength:    (trace[:strength] || 0).round(3),
    confidence:  (trace[:confidence] || 0.5).round(3),
    domain_tags: trace[:domain_tags] || []
  }
end

.freshness_assessment(traces) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 124

def freshness_assessment(traces)
  now = Time.now.utc
  ages = traces.map { |t| now - (t[:last_reinforced] || t[:created_at] || now) }
  avg_age = ages.sum / ages.size

  {
    avg_age_seconds: avg_age.round(1),
    freshest:        ages.min.round(1),
    stalest:         ages.max.round(1),
    label:           freshness_label(avg_age)
  }
end

.freshness_label(avg_age) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 137

def freshness_label(avg_age)
  if avg_age < 60       then :very_fresh
  elsif avg_age < 3600  then :fresh
  elsif avg_age < 86_400 then :aging
  else :stale
  end
end

.group_by_type(traces) ⇒ Object



32
33
34
35
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 32

def group_by_type(traces)
  grouped = traces.group_by { |t| t[:trace_type] || :unknown }
  grouped.sort_by { |type, _| Constants::TYPE_PRIORITY[type] || 99 }.to_h
end

.limit_per_type(type, total_limit) ⇒ Object



158
159
160
161
162
163
164
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 158

def limit_per_type(type, total_limit)
  case type
  when :firmware, :identity then [total_limit, 3].min
  when :procedural          then [total_limit, 2].min
  else [total_limit, 5].min
  end
end

.strength_stats(traces) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 91

def strength_stats(traces)
  strengths = traces.map { |t| t[:strength] || 0 }
  {
    mean:   (strengths.sum / strengths.size).round(3),
    max:    strengths.max.round(3),
    min:    strengths.min.round(3),
    strong: strengths.count { |s| s >= 0.5 },
    weak:   strengths.count { |s| s < 0.3 }
  }
end

.summarize_domain(traces, domain:, depth: :standard) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 12

def summarize_domain(traces, domain:, depth: :standard)
  return nil unless Constants::DEPTHS.include?(depth.to_sym)

  return empty_summary(domain) if traces.empty?

  grouped = group_by_type(traces)
  knowledge_level = classify_knowledge(traces.size)

  {
    domain:          domain,
    knowledge_level: knowledge_level,
    trace_count:     traces.size,
    type_breakdown:  type_breakdown(grouped),
    key_facts:       extract_key_facts(grouped, depth: depth),
    strength_stats:  strength_stats(traces),
    emotional_tone:  emotional_tone(traces),
    freshness:       freshness_assessment(traces)
  }
end

.tone_label(valence, intensity) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 116

def tone_label(valence, intensity)
  if intensity < 0.2      then :neutral
  elsif valence > 0.3     then :positive
  elsif valence < -0.3    then :negative
  else :mixed
  end
end

.type_breakdown(grouped) ⇒ Object



37
38
39
# File 'lib/legion/extensions/agentic/language/language/helpers/summarizer.rb', line 37

def type_breakdown(grouped)
  grouped.transform_values(&:size)
end