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 +4 -4
- data/VERSION +1 -1
- data/lib/active_genie/battle/basic.rb +1 -2
- data/lib/active_genie/configuration/providers/openai_config.rb +3 -3
- data/lib/active_genie/ranking/README.md +1 -31
- data/lib/active_genie/ranking/elo_round.rb +0 -3
- data/lib/active_genie/ranking/free_for_all.rb +0 -3
- data/lib/active_genie/ranking/player.rb +5 -17
- data/lib/active_genie/ranking/players_collection.rb +1 -5
- data/lib/active_genie/ranking/ranking.rb +2 -18
- data/lib/active_genie/ranking/ranking_scoring.rb +4 -26
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce95fdbe75d4d49e33eebf773847c534a52e9193ec44b3292aba0dd2dcac6fd4
|
4
|
+
data.tar.gz: 95130aa00f70d219ecea862d74413179a43f72a96f2a1ab22406413f246b0695
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c977f74b8d5603f28f823c5d6efffe5a345f4c47a6ee818edaaab57e0372769578420dd03de29bc51ac0a5f2107c7fc8365f7fbd114a5a02c146499b91e6988
|
7
|
+
data.tar.gz: b3b9fb9986cb24c7065b5e95528a0a6212dccc452224b017ae68ad9452eb7c944bceac9e832e089886a67d2093040418c7596847bad544b1e1c873923dd6f78c
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
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-
|
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-
|
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 || '
|
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,
|
20
|
-
:ffa_lose_count, :ffa_draw_count,
|
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:,
|
60
|
+
id:, content:, score:, elo:,
|
73
61
|
ffa_win_count:, ffa_lose_count:, ffa_draw_count:,
|
74
|
-
eliminated:, ffa_score
|
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.
|
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
|
-
|
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
|
-
@
|
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
|
-
|
29
|
-
|
30
|
-
|
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)
|
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.
|
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:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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: []
|