active_genie 0.0.21 → 0.0.23

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9c9c17c2c02f617c53edd6177ff72e0e2da34a4faf6bbeb9f9698b3858e4b69
4
- data.tar.gz: 777620b958c17c9a439fcf5b8bdb3195564005e5becd8c41955c1c255c1a6ad3
3
+ metadata.gz: ce95fdbe75d4d49e33eebf773847c534a52e9193ec44b3292aba0dd2dcac6fd4
4
+ data.tar.gz: 95130aa00f70d219ecea862d74413179a43f72a96f2a1ab22406413f246b0695
5
5
  SHA512:
6
- metadata.gz: c3bee8941701e3516f48106d96165d78ea279cea1c7e5623515aed3361b5a337e191c85a3e4774a9526e3412a4b11f4c4f5d766e7f5a0e827cc74d869bd1ca54
7
- data.tar.gz: a489c2f042aee21501697dfac47d0a37bd1a8bf50d990472dda2f7f8567615c3efd4422500653ac798c425a65df7bc065afaa3337f08a16305d4ef8f0b254a05
6
+ metadata.gz: 7c977f74b8d5603f28f823c5d6efffe5a345f4c47a6ee818edaaab57e0372769578420dd03de29bc51ac0a5f2107c7fc8365f7fbd114a5a02c146499b91e6988
7
+ data.tar.gz: b3b9fb9986cb24c7065b5e95528a0a6212dccc452224b017ae68ad9452eb7c944bceac9e832e089886a67d2093040418c7596847bad544b1e1c873923dd6f78c
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.21
1
+ 0.0.23
@@ -122,8 +122,7 @@ module ActiveGenie::Battle
122
122
  description: 'Who is the winner based on the impartial judge reasoning?',
123
123
  enum: ['player_1', 'player_2']
124
124
  },
125
- },
126
- required: %w[player_1_sell_himself player_2_sell_himself player_1_arguments player_2_counter impartial_judge_winner_reasoning impartial_judge_winner]
125
+ }
127
126
  }
128
127
  }
129
128
  end
@@ -33,21 +33,21 @@ module ActiveGenie
33
33
  # Defaults to 'gpt-4o-mini'.
34
34
  # @return [String] The lower tier model name.
35
35
  def lower_tier_model
36
- @lower_tier_model || 'gpt-4.1-mini'
36
+ @lower_tier_model || 'gpt-4o-mini'
37
37
  end
38
38
 
39
39
  # Retrieves the model name designated for the middle tier (e.g., balanced performance).
40
40
  # Defaults to 'gpt-4o'.
41
41
  # @return [String] The middle tier model name.
42
42
  def middle_tier_model
43
- @middle_tier_model || 'gpt-4.1'
43
+ @middle_tier_model || 'gpt-4o'
44
44
  end
45
45
 
46
46
  # Retrieves the model name designated for the upper tier (e.g., most capable).
47
47
  # Defaults to 'o1-preview'.
48
48
  # @return [String] The upper tier model name.
49
49
  def upper_tier_model
50
- @upper_tier_model || 'o3-mini'
50
+ @upper_tier_model || 'o1-preview'
51
51
  end
52
52
  end
53
53
  end
@@ -40,34 +40,4 @@ The method processes the players through scoring, elimination, and ranking phase
40
40
  - Adjust initial criteria to ensure consistency
41
41
  - Adjust each player's content to ensure consistency
42
42
  - Support players with images or audio
43
- - Parallelize processing battles and scoring
44
-
45
- ## Ranking Configuration
46
-
47
- | Config | Description | Default |
48
- |--------|-------------|---------|
49
- | `score_variation_threshold` | Threshold for eliminating players with inconsistent scores | `30` |
50
-
51
- ## Ranking Callbacks
52
- Callbacks are optional and can be used to watch any changes in players, battles, or scoring.
53
-
54
- | Callback | Description |
55
- |--------|-------------|
56
- | `watch_players` | Callback to watch any changes in players |
57
- | `watch_battles` | Callback to watch any changes in battles |
58
- | `watch_scoring` | Callback to watch any changes in scoring |
59
-
60
- Example of callback usage:
61
-
62
- ```ruby
63
- result = ActiveGenie::Ranking.call(
64
- players,
65
- criteria,
66
- config: {
67
- watch_players: ->(player) { puts player },
68
- watch_battles: ->(battle) { puts battle },
69
- watch_scoring: ->(scoring) { puts scoring }
70
- }
71
- )
72
- ```
73
-
43
+ - Parallelize processing battles and scoring
@@ -76,9 +76,6 @@ module ActiveGenie::Ranking
76
76
  when 'draw' then [nil, nil]
77
77
  end
78
78
 
79
- @config[:runtime][:watch_battle].call({ id: "#{player_1.id}_#{player_2.id}_#{elo_round_id}", player_1:, player_2:, winner:, loser:, reasoning: result['reasoning'] }) if @config[:runtime][:watch_battle]
80
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
81
-
82
79
  [winner, loser]
83
80
  end
84
81
  end
@@ -26,8 +26,6 @@ module ActiveGenie::Ranking
26
26
  winner.win!
27
27
  loser.lose!
28
28
  end
29
-
30
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
31
29
  end
32
30
  end
33
31
 
@@ -58,7 +56,6 @@ module ActiveGenie::Ranking
58
56
  when 'draw' then [nil, nil, result['reasoning']]
59
57
  end
60
58
 
61
- @config[:runtime][:watch_battle].call({ id: "#{player_1.id}_#{player_2.id}_#{free_for_all_id}", player_1:, player_2:, winner:, loser:, reasoning: result['reasoning'] }) if @config[:runtime][:watch_battle]
62
59
  ActiveGenie::Logger.debug({
63
60
  code: :free_for_all_battle,
64
61
  player_ids: [player_1.id, player_2.id],
@@ -6,7 +6,6 @@ module ActiveGenie::Ranking
6
6
  params = { content: params } if params.is_a?(String)
7
7
 
8
8
  @content = params.dig(:content) || params
9
- @name = params.dig(:name) || params.dig(:content)[0..10]
10
9
  @id = params.dig(:id) || Digest::MD5.hexdigest(@content)
11
10
  @score = params.dig(:score) || nil
12
11
  @elo = params.dig(:elo) || nil
@@ -16,8 +15,9 @@ module ActiveGenie::Ranking
16
15
  @eliminated = params.dig(:eliminated) || nil
17
16
  end
18
17
 
19
- attr_reader :id, :content, :score, :elo, :ffa_win_count,
20
- :ffa_lose_count, :ffa_draw_count, :eliminated
18
+ attr_reader :id, :content, :score, :elo,
19
+ :ffa_win_count, :ffa_lose_count, :ffa_draw_count,
20
+ :eliminated
21
21
  attr_accessor :rank
22
22
 
23
23
  def score=(value)
@@ -51,27 +51,15 @@ module ActiveGenie::Ranking
51
51
  ActiveGenie::Logger.debug({ code: :new_ffa_score, player_id: id, result: 'lose', ffa_score: })
52
52
  end
53
53
 
54
- def name
55
- @name
56
- end
57
-
58
54
  def ffa_score
59
55
  @ffa_win_count * 3 + @ffa_draw_count
60
56
  end
61
57
 
62
- def sort_value
63
- (ffa_score * 1000000) + ((elo || 0) * 100) + (score || 0)
64
- end
65
-
66
- def to_json
67
- to_h.to_json
68
- end
69
-
70
58
  def to_h
71
59
  {
72
- id:, name:, content:, score:, elo:,
60
+ id:, content:, score:, elo:,
73
61
  ffa_win_count:, ffa_lose_count:, ffa_draw_count:,
74
- eliminated:, ffa_score:, sort_value:
62
+ eliminated:, ffa_score:
75
63
  }
76
64
  end
77
65
 
@@ -41,14 +41,10 @@ module ActiveGenie::Ranking
41
41
  end
42
42
 
43
43
  def sorted
44
- sorted_players = @players.sort_by { |p| -p.sort_value }
44
+ sorted_players = @players.sort_by { |p| [-p.ffa_score, -(p.elo || 0), -(p.score || 0)] }
45
45
  sorted_players.each_with_index { |p, i| p.rank = i + 1 }
46
46
  sorted_players
47
47
  end
48
-
49
- def to_json
50
- to_h.to_json
51
- end
52
48
 
53
49
  def to_h
54
50
  sorted.map { |p| p.to_h }
@@ -67,7 +67,7 @@ module ActiveGenie::Ranking
67
67
 
68
68
  private
69
69
 
70
- DEFAULT_SCORE_VARIATION_THRESHOLD = 30
70
+ SCORE_VARIATION_THRESHOLD = 15
71
71
  ELIMINATION_VARIATION = 'variation_too_high'
72
72
  ELIMINATION_RELEGATION = 'relegation_tier'
73
73
 
@@ -80,36 +80,27 @@ module ActiveGenie::Ranking
80
80
  end
81
81
 
82
82
  def set_initial_player_scores!
83
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
84
83
  RankingScoring.call(@players, @criteria, reviewers: @reviewers, config: @config)
85
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
86
84
  end
87
85
 
88
86
  def eliminate_obvious_bad_players!
89
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
90
- while @players.coefficient_of_variation >= score_variation_threshold
87
+ while @players.coefficient_of_variation >= SCORE_VARIATION_THRESHOLD
91
88
  @players.eligible.last.eliminated = ELIMINATION_VARIATION
92
89
  end
93
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
94
90
  end
95
91
 
96
92
  def run_elo_round!
97
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
98
93
  @elo_rounds_played += 1
99
94
 
100
95
  elo_report = EloRound.call(@players, @criteria, config: @config)
101
96
 
102
97
  @elo_round_battle_count += elo_report[:battles_count]
103
98
 
104
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
105
99
  elo_report
106
100
  end
107
101
 
108
102
  def eliminate_relegation_players!
109
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
110
103
  @players.calc_relegation_tier.each { |player| player.eliminated = ELIMINATION_RELEGATION }
111
-
112
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
113
104
  end
114
105
 
115
106
  def rebalance_players!(elo_report)
@@ -120,19 +111,12 @@ module ActiveGenie::Ranking
120
111
 
121
112
  player.elo += elo_report[:highest_elo_diff]
122
113
  end
123
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
124
114
  end
125
115
 
126
116
  def run_free_for_all!
127
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
128
117
  ffa_report = FreeForAll.call(@players, @criteria, config: @config)
129
118
 
130
119
  @free_for_all_battle_count += ffa_report[:battles_count]
131
- @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
132
- end
133
-
134
- def score_variation_threshold
135
- @config[:runtime][:score_variation_threshold] || DEFAULT_SCORE_VARIATION_THRESHOLD
136
120
  end
137
121
 
138
122
  def report
@@ -16,27 +16,10 @@ module ActiveGenie::Ranking
16
16
  def call
17
17
  ActiveGenie::Logger.with_context(log_context) do
18
18
  @reviewers = generate_reviewers
19
-
20
- players_to_score = players_without_score
21
- until players_to_score.empty?
22
- threads = []
23
- mutex = Mutex.new
24
-
25
- # Take up to 3 players for parallel processing
26
- current_batch = players_to_score.shift(3)
27
19
 
28
- current_batch.each do |player|
29
- threads << Thread.new(player) do |p|
30
- score = generate_score(p)
31
-
32
- mutex.synchronize do
33
- p.score = score
34
- end
35
- end
36
- end
37
-
38
- # Wait for all threads in this batch to complete
39
- threads.each(&:join)
20
+ players_without_score.each do |player|
21
+ # TODO: This can take a while, can be parallelized
22
+ player.score = generate_score(player)
40
23
  end
41
24
  end
42
25
  end
@@ -56,11 +39,6 @@ module ActiveGenie::Ranking
56
39
  ).values_at('final_score', 'final_reasoning')
57
40
 
58
41
  ActiveGenie::Logger.debug({ code: :new_score, player_id: player.id, score:, reasoning: })
59
- @config[:runtime][:watch_scoring].call({
60
- player_id: player.id,
61
- player_name: player.content[0..10],
62
- score: player.score
63
- }) if @config[:runtime][:watch_scoring]
64
42
 
65
43
  score
66
44
  end
@@ -87,7 +65,7 @@ module ActiveGenie::Ranking
87
65
  player_ids = players_without_score.map(&:id).join(',')
88
66
  ranking_unique_key = [player_ids, @criteria, @config.to_json].join('-')
89
67
 
90
- Digest::MD5.hexdigest(ranking_unique_key) + '-scoring'
68
+ Digest::MD5.hexdigest(ranking_unique_key)
91
69
  end
92
70
  end
93
71
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_genie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.21
4
+ version: 0.0.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Radamés Roriz
@@ -9,21 +9,22 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: "# ActiveGenie \U0001F9DE‍♂️\n> The lodash for GenAI, stop reinventing
13
- the wheel\n\nActiveGenie is a Ruby gem that provides valuable solutions powered
14
- by Generative AI (GenAI) models. Just like Lodash or ActiveStorage, ActiveGenie
15
- brings a set of Modules to reach real value fast and reliably.\nActiveGenie is backed
16
- by a custom benchmarking system that ensures consistent quality and performance
17
- across different models and providers in every release.\n\n## Features\n\n* **Data
18
- Extractor:** Extract structured data from text using AI-powered analysis\n* **Scoring:**
19
- Text evaluation system with detailed scoring and feedback\n* **Battle:** AI-powered
20
- battle evaluation system between two players\n* **Ranking:** Multi-phase ranking
21
- system for multiple options\n\n### Performance Breakdown\n\n| ActiveGenie Module
22
- | Best Precision | Worst Precision | Recommended Model |\n|--------------------|-------------------|-------------------|-------------------|\n|
23
- data_extractor | 100% | 86% | `gpt-4o-mini` |\n| battle | 100% | 10% | `gemini-2.0-flash-lite`
24
- |\n| scoring | 69% | 61% | `claude-3-5-haiku-20241022` |\n| ranking | 100% | 0%
25
- | `gemini-2.0-flash-lite` |\n\nSee the [GitHub repository](https://github.com/Roriz/active_genie)
26
- for complete documentation and examples.\n"
12
+ description: |
13
+ == ActiveGenie
14
+
15
+ The lodash for GenAI, stop reinventing the wheel
16
+
17
+ ActiveGenie is a Ruby gem that provides valuable solutions powered by Generative AI (GenAI) models. Just like Lodash or ActiveStorage, ActiveGenie brings a set of Modules to reach real value fast and reliably.
18
+ ActiveGenie is backed by a custom benchmarking system that ensures consistent quality and performance across different models and providers in every release.
19
+
20
+ == Features
21
+
22
+ * Data Extractor: (100% precision) Extract structured data from text using AI-powered analysis
23
+ * Scoring: (69% precision) Text evaluation system with detailed scoring and feedback
24
+ * Battle: (100% precision) AI-powered battle evaluation system between two players
25
+ * Ranking: (100% precision) Multi-phase ranking system for multiple options
26
+
27
+ See the GitHub repository at https://github.com/Roriz/active_genie for complete documentation and examples.
27
28
  email:
28
29
  - radames@roriz.dev
29
30
  executables: []