Class: Legion::Extensions::Agentic::Inference::PredictiveCoding::Helpers::GenerativeModel

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_id: nil) ⇒ GenerativeModel

Returns a new instance of GenerativeModel.



12
13
14
15
16
17
18
19
20
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 12

def initialize(model_id: nil)
  @model_id        = model_id || SecureRandom.uuid
  @created_at      = Time.now.utc
  @predictions     = {}    # domain -> { value, confidence, updated_at }
  @error_history   = []    # array of PredictionError objects (capped)
  @precisions      = {}    # domain -> float (0..1)
  @free_energy_ema = 0.0
  @domain_models   = {}    # domain -> simple weighted mean tracker
end

Instance Attribute Details

#created_atObject (readonly)

Returns the value of attribute created_at.



10
11
12
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 10

def created_at
  @created_at
end

#model_idObject (readonly)

Returns the value of attribute model_id.



10
11
12
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 10

def model_id
  @model_id
end

Instance Method Details

#active_inference_candidatesObject



65
66
67
68
69
70
71
72
73
74
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 65

def active_inference_candidates
  @domain_models.keys.select do |domain|
    precision = @precisions.fetch(domain, Constants::DEFAULT_PRECISION)
    recent_errors = recent_errors_for(domain)
    next false if recent_errors.empty?

    avg_error = recent_errors.sum(&:error_magnitude) / recent_errors.size
    avg_error > Constants::SURPRISE_THRESHOLD && precision < 0.6
  end
end

#all_errorsObject



80
81
82
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 80

def all_errors
  @error_history
end

#decay_allObject



84
85
86
87
88
89
90
91
92
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 84

def decay_all
  @precisions.each_key do |domain|
    current = @precisions[domain]
    decayed = [current - Constants::PRECISION_DECAY, Constants::PRECISION_FLOOR].max
    @precisions[domain] = decayed
  end

  prune_old_errors
end

#domain_countObject



94
95
96
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 94

def domain_count
  @domain_models.size
end

#error_countObject



98
99
100
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 98

def error_count
  @error_history.size
end

#free_energyObject



53
54
55
56
57
58
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 53

def free_energy
  prediction_error_term = average_weighted_error
  complexity_term       = @domain_models.size * Constants::COMPLEXITY_PENALTY
  @free_energy_ema      = ema(@free_energy_ema, prediction_error_term + complexity_term, Constants::FREE_ENERGY_ALPHA)
  @free_energy_ema
end

#free_energy_levelObject



60
61
62
63
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 60

def free_energy_level
  fe = free_energy
  Constants::FREE_ENERGY_LEVELS.find { |_k, range| range.cover?(fe) }&.first || :unknown
end

#precision_for(domain:) ⇒ Object



49
50
51
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 49

def precision_for(domain:)
  @precisions.fetch(domain, Constants::DEFAULT_PRECISION)
end

#predict(domain:, context: {}) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 22

def predict(domain:, context: {})
  prior = @domain_models[domain]
  if prior
    confidence = @precisions.fetch(domain, Constants::DEFAULT_PRECISION)
    value      = prior[:mean]
  else
    confidence = Constants::DEFAULT_PRECISION
    value      = context[:expected] || context[:baseline] || 0.5
  end

  @predictions[domain] = { value: value, confidence: confidence, updated_at: Time.now.utc }

  { domain: domain, predicted: value, confidence: confidence }
end

#surprising_errorsObject



76
77
78
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 76

def surprising_errors
  @error_history.select(&:surprising?)
end

#to_hObject



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

def to_h
  {
    model_id:          @model_id,
    created_at:        @created_at,
    domain_count:      @domain_models.size,
    error_count:       @error_history.size,
    free_energy:       free_energy.round(4),
    free_energy_level: free_energy_level,
    surprising_count:  surprising_errors.size,
    domains:           domain_stats
  }
end

#update(domain:, predicted:, actual:) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/legion/extensions/agentic/inference/predictive_coding/helpers/generative_model.rb', line 37

def update(domain:, predicted:, actual:)
  precision = @precisions.fetch(domain, Constants::DEFAULT_PRECISION)
  error     = PredictionError.new(domain: domain, predicted: predicted, actual: actual, precision: precision)

  record_error(error)
  update_precision(domain, error.error_magnitude)
  update_domain_model(domain, actual)
  update_free_energy(error.error_magnitude)

  error
end