Module: Legion::Extensions::Agentic::Affect::Empathy::Runners::Empathy

Includes:
Helpers::Lex
Included in:
Client
Defined in:
lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb

Instance Method Summary collapse

Instance Method Details

#decay_modelsObject



107
108
109
110
111
112
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 107

def decay_models(**)
  decayed = model_store.decay_all
  removed = model_store.remove_stale
  log.debug("[empathy] decay: updated=#{decayed} stale_removed=#{removed}")
  { decayed: decayed, stale_removed: removed }
end

#empathy_statsObject



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 114

def empathy_stats(**)
  models = model_store.all_models
  accuracies = models.filter_map(&:prediction_accuracy)

  {
    tracked_agents:      model_store.size,
    total_predictions:   models.sum { |m| m.predictions.size },
    avg_accuracy:        accuracies.empty? ? nil : (accuracies.sum / accuracies.size).round(3),
    stale_models:        models.count(&:stale?),
    cooperation_stances: stance_distribution(models)
  }
end

#observe_agent(agent_id:, observation: {}) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 27

def observe_agent(agent_id:, observation: {}, **)
  model = model_store.update(agent_id, observation)
  log.debug("[empathy] observed: agent=#{agent_id} emotion=#{model.emotional_state} " \
            "cooperation=#{model.cooperation_stance}")

  {
    agent_id:           agent_id,
    emotional_state:    model.emotional_state,
    cooperation_stance: model.cooperation_stance,
    believed_goal:      model.believed_goal,
    confidence:         model.confidence_level
  }
end

#observe_human_observations(human_observations: []) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 13

def observe_human_observations(human_observations: [], **)
  return { observed: 0, identities: [] } if human_observations.empty?

  identities = human_observations.map do |obs|
    model_store.update_from_human_observation(obs)
    obs[:identity].to_s
  end

  log.debug("[empathy] human_observations: count=#{identities.size} " \
            "identities=#{identities.join(',')}")

  { observed: identities.size, identities: identities }
end

#perspective_take(agent_id:) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 73

def perspective_take(agent_id:, **)
  model = model_store.get(agent_id)
  return { error: :no_model, agent_id: agent_id } unless model

  narrative = build_perspective_narrative(model)
  log.debug("[empathy] perspective: agent=#{agent_id}")

  {
    agent_id:  agent_id,
    narrative: narrative,
    model:     model.to_h
  }
end

#predict_reaction(agent_id:, scenario: {}) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 41

def predict_reaction(agent_id:, scenario: {}, **)
  prediction = model_store.predict(agent_id, scenario)

  if prediction
    log.debug("[empathy] prediction: agent=#{agent_id} response=#{prediction[:likely_response]} " \
              "confidence=#{prediction[:confidence].round(2)}")
    prediction
  else
    log.debug("[empathy] no model for agent=#{agent_id}")
    { error: :no_model, agent_id: agent_id }
  end
end

#record_outcome(agent_id:, prediction_id:, actual_response:, accurate:) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 54

def record_outcome(agent_id:, prediction_id:, actual_response:, accurate:, **)
  model = model_store.get(agent_id)
  return { error: :no_model } unless model

  result = model.record_prediction_outcome(
    prediction_id:   prediction_id,
    actual_response: actual_response,
    accurate:        accurate
  )

  if result.nil?
    { error: :prediction_not_found }
  else
    log.info("[empathy] outcome recorded: agent=#{agent_id} accurate=#{accurate} " \
             "accuracy=#{model.prediction_accuracy&.round(2)}")
    { agent_id: agent_id, accurate: accurate, current_accuracy: model.prediction_accuracy }
  end
end

#social_landscapeObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/legion/extensions/agentic/affect/empathy/runners/empathy.rb', line 87

def social_landscape(**)
  models = model_store.all_models
  cooperative = model_store.by_cooperation(:cooperative).size
  competitive = model_store.by_cooperation(:competitive).size
  stressed = model_store.by_emotion(:stressed).size + model_store.by_emotion(:frustrated).size

  log.debug("[empathy] landscape: agents=#{models.size} cooperative=#{cooperative} " \
            "competitive=#{competitive} stressed=#{stressed}")

  {
    tracked_agents:    models.size,
    cooperative_count: cooperative,
    competitive_count: competitive,
    stressed_count:    stressed,
    stances:           stance_distribution(models),
    emotions:          emotion_distribution(models),
    overall_climate:   assess_climate(cooperative, competitive, stressed, models.size)
  }
end