active_genie 0.26.5 → 0.27.1
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/README.md +10 -193
- data/VERSION +1 -1
- data/lib/active_genie/battle/generalist.rb +9 -9
- data/lib/active_genie/clients/providers/anthropic_client.rb +2 -2
- data/lib/active_genie/clients/providers/base_client.rb +2 -2
- data/lib/active_genie/clients/providers/deepseek_client.rb +2 -2
- data/lib/active_genie/clients/providers/google_client.rb +3 -10
- data/lib/active_genie/clients/providers/openai_client.rb +2 -2
- data/lib/active_genie/config/log_config.rb +12 -15
- data/lib/active_genie/config/providers/anthropic_config.rb +2 -2
- data/lib/active_genie/config/providers/deepseek_config.rb +2 -2
- data/lib/active_genie/config/providers/google_config.rb +2 -2
- data/lib/active_genie/config/providers/openai_config.rb +2 -2
- data/lib/active_genie/config/providers/provider_base.rb +4 -4
- data/lib/active_genie/configuration.rb +16 -4
- data/lib/active_genie/data_extractor/generalist.rb +2 -2
- data/lib/active_genie/logger.rb +40 -22
- data/lib/active_genie/ranking/elo_round.rb +30 -37
- data/lib/active_genie/ranking/free_for_all.rb +29 -28
- data/lib/active_genie/ranking/player.rb +1 -9
- data/lib/active_genie/ranking/ranking.rb +32 -25
- data/lib/active_genie/ranking/ranking_scoring.rb +12 -17
- data/lib/active_genie/scoring/generalist.rb +9 -9
- data/lib/tasks/templates/active_genie.rb +1 -1
- metadata +8 -13
- data/lib/active_genie/data_extractor/README.md +0 -131
- data/lib/active_genie/ranking/README.md +0 -73
- data/lib/active_genie/ranking/concerns/loggable.rb +0 -29
- data/lib/active_genie/scoring/README.md +0 -76
- /data/lib/active_genie/battle/{generalist.md → generalist.prompt.md} +0 -0
- /data/lib/active_genie/data_extractor/{generalist.md → generalist.prompt.md} +0 -0
- /data/lib/active_genie/scoring/{generalist.md → generalist.prompt.md} +0 -0
data/lib/active_genie/logger.rb
CHANGED
@@ -4,47 +4,65 @@ require 'json'
|
|
4
4
|
require 'fileutils'
|
5
5
|
|
6
6
|
module ActiveGenie
|
7
|
-
|
8
|
-
|
7
|
+
class Logger
|
8
|
+
def initialize(log_config: nil)
|
9
|
+
@log_config = log_config || ActiveGenie.configuration.log
|
10
|
+
end
|
9
11
|
|
10
12
|
def call(data)
|
11
|
-
log =
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
}
|
13
|
+
log = data.merge(@log_config.additional_context)
|
14
|
+
.merge(
|
15
|
+
timestamp: Time.now,
|
16
|
+
process_id: Process.pid
|
17
|
+
)
|
17
18
|
|
18
19
|
persist!(log)
|
19
|
-
|
20
|
+
output_call(log)
|
21
|
+
call_observers(log)
|
20
22
|
|
21
23
|
log
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
def merge(log_config = nil)
|
27
|
+
new(log_config:)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def call_observers(log)
|
33
|
+
Array(@log_config.observers).each do |observer|
|
34
|
+
next unless observer[:scope].all? { |key, value| log[key.to_sym] == value }
|
35
|
+
|
36
|
+
observer[:observer]&.call(log)
|
37
|
+
rescue StandardError => e
|
38
|
+
call(code: :observer_error, **observer, error: e.message)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
36
|
-
|
42
|
+
def output_call(log)
|
43
|
+
if @log_config.output
|
44
|
+
@log_config.output&.call(log)
|
45
|
+
else
|
46
|
+
$stdout.puts log
|
47
|
+
end
|
48
|
+
rescue StandardError => e
|
49
|
+
call(code: :output_error, error: e.message)
|
50
|
+
end
|
37
51
|
|
38
52
|
def persist!(log)
|
39
|
-
file_path = log
|
53
|
+
file_path = log_to_file_path(log)
|
40
54
|
folder_path = File.dirname(file_path)
|
41
55
|
|
42
56
|
FileUtils.mkdir_p(folder_path)
|
43
57
|
File.write(file_path, "#{JSON.generate(log)}\n", mode: 'a')
|
44
58
|
end
|
45
59
|
|
46
|
-
def
|
47
|
-
|
60
|
+
def log_to_file_path(log)
|
61
|
+
if log.key?(:fine_tune) && log[:fine_tune]
|
62
|
+
@log_config.fine_tune_file_path
|
63
|
+
else
|
64
|
+
@log_config.file_path
|
65
|
+
end
|
48
66
|
end
|
49
67
|
end
|
50
68
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../battle/generalist'
|
4
|
-
|
5
3
|
module ActiveGenie
|
6
4
|
module Ranking
|
7
5
|
class EloRound
|
@@ -9,27 +7,26 @@ module ActiveGenie
|
|
9
7
|
new(...).call
|
10
8
|
end
|
11
9
|
|
12
|
-
def initialize(players, criteria, config:
|
10
|
+
def initialize(players, criteria, config: nil)
|
13
11
|
@players = players
|
14
12
|
@relegation_tier = players.calc_relegation_tier
|
15
13
|
@defender_tier = players.calc_defender_tier
|
16
14
|
@criteria = criteria
|
17
|
-
@config = config
|
15
|
+
@config = ActiveGenie.configuration.merge(config)
|
18
16
|
@tmp_defenders = []
|
19
17
|
@total_tokens = 0
|
20
|
-
@previous_elo = {}
|
18
|
+
@previous_elo = @players.to_h { |player| [player.id, player.elo] }
|
21
19
|
@previous_highest_elo = @defender_tier.max_by(&:elo).elo
|
22
20
|
end
|
23
21
|
|
24
22
|
def call
|
25
|
-
@
|
23
|
+
@config.log.add_observer(observers: ->(log) { log_observer(log) })
|
24
|
+
@config.log.additional_context = { elo_round_id: }
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
update_players_elo(winner, loser)
|
32
|
-
end
|
26
|
+
matches.each do |player_a, player_b|
|
27
|
+
# TODO: battle can take a while, can be parallelized
|
28
|
+
winner, loser = battle(player_a, player_b)
|
29
|
+
update_players_elo(winner, loser)
|
33
30
|
end
|
34
31
|
|
35
32
|
build_report
|
@@ -62,22 +59,20 @@ module ActiveGenie
|
|
62
59
|
end
|
63
60
|
|
64
61
|
def battle(player_a, player_b)
|
65
|
-
ActiveGenie::
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
[winner, loser]
|
80
|
-
end
|
62
|
+
result = ActiveGenie::Battle.call(
|
63
|
+
player_a.content,
|
64
|
+
player_b.content,
|
65
|
+
@criteria,
|
66
|
+
config: @config.merge(additional_context: { player_a_id: player_a.id, player_b_id: player_b.id })
|
67
|
+
)
|
68
|
+
|
69
|
+
winner, loser = case result['winner']
|
70
|
+
when 'player_a' then [player_a, player_b]
|
71
|
+
when 'player_b' then [player_b, player_a]
|
72
|
+
when 'draw' then [nil, nil]
|
73
|
+
end
|
74
|
+
|
75
|
+
[winner, loser]
|
81
76
|
end
|
82
77
|
|
83
78
|
def update_players_elo(winner, loser)
|
@@ -94,16 +89,14 @@ module ActiveGenie
|
|
94
89
|
player_rating + (K * (score - expected_score)).round
|
95
90
|
end
|
96
91
|
|
97
|
-
def log_context
|
98
|
-
{ elo_round_id: }
|
99
|
-
end
|
100
|
-
|
101
92
|
def elo_round_id
|
102
|
-
|
103
|
-
|
93
|
+
@elo_round_id ||= begin
|
94
|
+
relegation_tier_ids = @relegation_tier.map(&:id).join(',')
|
95
|
+
defender_tier_ids = @defender_tier.map(&:id).join(',')
|
104
96
|
|
105
|
-
|
106
|
-
|
97
|
+
ranking_unique_key = [relegation_tier_ids, defender_tier_ids, @criteria, @config.to_json].join('-')
|
98
|
+
Digest::MD5.hexdigest(ranking_unique_key)
|
99
|
+
end
|
107
100
|
end
|
108
101
|
|
109
102
|
def build_report
|
@@ -118,7 +111,7 @@ module ActiveGenie
|
|
118
111
|
players_elo_diff:
|
119
112
|
}
|
120
113
|
|
121
|
-
|
114
|
+
@config.logger.call({ elo_round_id:, code: :elo_round_report, **report })
|
122
115
|
|
123
116
|
report
|
124
117
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../battle/generalist'
|
4
|
-
|
5
3
|
module ActiveGenie
|
6
4
|
module Ranking
|
7
5
|
class FreeForAll
|
@@ -9,21 +7,22 @@ module ActiveGenie
|
|
9
7
|
new(...).call
|
10
8
|
end
|
11
9
|
|
12
|
-
def initialize(players, criteria, config:
|
10
|
+
def initialize(players, criteria, config: nil)
|
13
11
|
@players = players
|
14
12
|
@criteria = criteria
|
15
|
-
@config = config
|
13
|
+
@config = config || ActiveGenie.configuration
|
16
14
|
@start_time = Time.now
|
17
15
|
@total_tokens = 0
|
18
16
|
end
|
19
17
|
|
20
18
|
def call
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
@config.log.add_observer(observers: ->(log) { log_observer(log) })
|
20
|
+
@config.log.additional_context = { free_for_all_id: }
|
21
|
+
|
22
|
+
matches.each do |player_a, player_b|
|
23
|
+
winner, loser = battle(player_a, player_b)
|
24
24
|
|
25
|
-
|
26
|
-
end
|
25
|
+
update_players_score(winner, loser)
|
27
26
|
end
|
28
27
|
|
29
28
|
build_report
|
@@ -38,26 +37,30 @@ module ActiveGenie
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def battle(player_a, player_b)
|
40
|
+
log_context = { player_a_id: player_a.id, player_b_id: player_b.id }
|
41
|
+
|
41
42
|
result = ActiveGenie::Battle.call(
|
42
43
|
player_a.content,
|
43
44
|
player_b.content,
|
44
45
|
@criteria,
|
45
|
-
config: @config
|
46
|
+
config: @config.merge(additional_context: log_context)
|
46
47
|
)
|
47
48
|
|
48
49
|
winner, loser = case result['winner']
|
49
|
-
when 'player_a' then [player_a, player_b
|
50
|
-
when 'player_b' then [player_b, player_a
|
51
|
-
when 'draw' then [nil, nil
|
50
|
+
when 'player_a' then [player_a, player_b]
|
51
|
+
when 'player_b' then [player_b, player_a]
|
52
|
+
when 'draw' then [nil, nil]
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
@config.logger.call(
|
56
|
+
{
|
57
|
+
**log_context,
|
58
|
+
code: :free_for_all_battle,
|
59
|
+
winner_id: winner&.id,
|
60
|
+
loser_id: loser&.id,
|
61
|
+
reasoning: result['reasoning']
|
62
|
+
}
|
63
|
+
)
|
61
64
|
|
62
65
|
[winner, loser]
|
63
66
|
end
|
@@ -74,14 +77,12 @@ module ActiveGenie
|
|
74
77
|
end
|
75
78
|
end
|
76
79
|
|
77
|
-
def log_context
|
78
|
-
{ free_for_all_id: }
|
79
|
-
end
|
80
|
-
|
81
80
|
def free_for_all_id
|
82
|
-
|
83
|
-
|
84
|
-
|
81
|
+
@free_for_all_id ||= begin
|
82
|
+
eligible_ids = @players.eligible.map(&:id).join(',')
|
83
|
+
ranking_unique_key = [eligible_ids, @criteria, @config.to_json].join('-')
|
84
|
+
Digest::MD5.hexdigest(ranking_unique_key)
|
85
|
+
end
|
85
86
|
end
|
86
87
|
|
87
88
|
def build_report
|
@@ -92,7 +93,7 @@ module ActiveGenie
|
|
92
93
|
total_tokens: @total_tokens
|
93
94
|
}
|
94
95
|
|
95
|
-
|
96
|
+
@config.logger.call({ code: :free_for_all_report, **report })
|
96
97
|
|
97
98
|
report
|
98
99
|
end
|
@@ -47,34 +47,26 @@ module ActiveGenie
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def score=(value)
|
50
|
-
ActiveGenie::Logger.call({ code: :new_score, player_id: id, score: value }) if value != @score
|
51
50
|
@score = value
|
52
51
|
@elo = generate_elo_by_score
|
53
52
|
end
|
54
53
|
|
55
54
|
def elo=(value)
|
56
|
-
ActiveGenie::Logger.call({ code: :new_elo, player_id: id, elo: value }) if value != @elo
|
57
55
|
@elo = value || BASE_ELO
|
58
56
|
end
|
59
57
|
|
60
|
-
|
61
|
-
ActiveGenie::Logger.call({ code: :new_eliminated, player_id: id, eliminated: value }) if value != @eliminated
|
62
|
-
@eliminated = value
|
63
|
-
end
|
58
|
+
attr_writer :eliminated
|
64
59
|
|
65
60
|
def draw!
|
66
61
|
@ffa_draw_count += 1
|
67
|
-
ActiveGenie::Logger.call({ code: :new_ffa_score, player_id: id, result: 'draw', ffa_score: })
|
68
62
|
end
|
69
63
|
|
70
64
|
def win!
|
71
65
|
@ffa_win_count += 1
|
72
|
-
ActiveGenie::Logger.call({ code: :new_ffa_score, player_id: id, result: 'win', ffa_score: })
|
73
66
|
end
|
74
67
|
|
75
68
|
def lose!
|
76
69
|
@ffa_lose_count += 1
|
77
|
-
ActiveGenie::Logger.call({ code: :new_ffa_score, player_id: id, result: 'lose', ffa_score: })
|
78
70
|
end
|
79
71
|
|
80
72
|
def ffa_score
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'concerns/loggable'
|
4
3
|
require_relative 'players_collection'
|
5
4
|
require_relative 'free_for_all'
|
6
5
|
require_relative 'elo_round'
|
@@ -32,8 +31,6 @@ require_relative 'ranking_scoring'
|
|
32
31
|
module ActiveGenie
|
33
32
|
module Ranking
|
34
33
|
class Ranking
|
35
|
-
include ActiveGenie::Concerns::Loggable
|
36
|
-
|
37
34
|
def self.call(...)
|
38
35
|
new(...).call
|
39
36
|
end
|
@@ -48,20 +45,19 @@ module ActiveGenie
|
|
48
45
|
|
49
46
|
def call
|
50
47
|
@players = create_players
|
48
|
+
@config.log.additional_context = { ranking_id: }
|
51
49
|
|
52
|
-
|
53
|
-
|
54
|
-
eliminate_obvious_bad_players!
|
55
|
-
|
56
|
-
while @players.elo_eligible?
|
57
|
-
elo_report = run_elo_round!
|
58
|
-
eliminate_relegation_players!
|
59
|
-
rebalance_players!(elo_report)
|
60
|
-
end
|
50
|
+
set_initial_player_scores!
|
51
|
+
eliminate_obvious_bad_players!
|
61
52
|
|
62
|
-
|
53
|
+
while @players.elo_eligible?
|
54
|
+
elo_report = run_elo_round!
|
55
|
+
eliminate_relegation_players!
|
56
|
+
rebalance_players!(elo_report)
|
63
57
|
end
|
64
58
|
|
59
|
+
run_free_for_all!
|
60
|
+
|
65
61
|
sorted_players
|
66
62
|
end
|
67
63
|
|
@@ -72,13 +68,18 @@ module ActiveGenie
|
|
72
68
|
|
73
69
|
def create_players
|
74
70
|
players = PlayersCollection.new(@param_players)
|
75
|
-
players.each { |p|
|
71
|
+
players.each { |p| @config.logger.call({ code: :new_player, player: p.to_h }) }
|
76
72
|
|
77
73
|
players
|
78
74
|
end
|
79
75
|
|
80
76
|
def set_initial_player_scores!
|
81
|
-
RankingScoring.call(
|
77
|
+
RankingScoring.call(
|
78
|
+
@players,
|
79
|
+
@criteria,
|
80
|
+
reviewers: @reviewers,
|
81
|
+
config: @config
|
82
|
+
)
|
82
83
|
end
|
83
84
|
|
84
85
|
def eliminate_obvious_bad_players!
|
@@ -88,7 +89,11 @@ module ActiveGenie
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def run_elo_round!
|
91
|
-
EloRound.call(
|
92
|
+
EloRound.call(
|
93
|
+
@players,
|
94
|
+
@criteria,
|
95
|
+
config: @config
|
96
|
+
)
|
92
97
|
end
|
93
98
|
|
94
99
|
def eliminate_relegation_players!
|
@@ -106,25 +111,27 @@ module ActiveGenie
|
|
106
111
|
end
|
107
112
|
|
108
113
|
def run_free_for_all!
|
109
|
-
FreeForAll.call(
|
114
|
+
FreeForAll.call(
|
115
|
+
@players,
|
116
|
+
@criteria,
|
117
|
+
config: @config
|
118
|
+
)
|
110
119
|
end
|
111
120
|
|
112
121
|
def sorted_players
|
113
122
|
players = @players.sorted
|
114
|
-
|
123
|
+
@config.logger.call({ ranking_id:, code: :ranking_final, players: players.map(&:to_h) })
|
115
124
|
|
116
125
|
players.map(&:to_h)
|
117
126
|
end
|
118
127
|
|
119
|
-
def log_context
|
120
|
-
{ ranking_id: }
|
121
|
-
end
|
122
|
-
|
123
128
|
def ranking_id
|
124
|
-
|
125
|
-
|
129
|
+
@ranking_id ||= begin
|
130
|
+
player_ids = @players.map(&:id).join(',')
|
131
|
+
ranking_unique_key = [player_ids, @criteria, @config.to_json].join('-')
|
126
132
|
|
127
|
-
|
133
|
+
Digest::MD5.hexdigest(ranking_unique_key)
|
134
|
+
end
|
128
135
|
end
|
129
136
|
end
|
130
137
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../scoring/recommended_reviewers'
|
4
|
-
|
5
3
|
module ActiveGenie
|
6
4
|
module Ranking
|
7
5
|
class RankingScoring
|
@@ -9,7 +7,7 @@ module ActiveGenie
|
|
9
7
|
new(...).call
|
10
8
|
end
|
11
9
|
|
12
|
-
def initialize(players, criteria, reviewers: [], config:
|
10
|
+
def initialize(players, criteria, reviewers: [], config: nil)
|
13
11
|
@players = players
|
14
12
|
@criteria = criteria
|
15
13
|
@config = ActiveGenie.configuration.merge(config)
|
@@ -17,12 +15,11 @@ module ActiveGenie
|
|
17
15
|
end
|
18
16
|
|
19
17
|
def call
|
20
|
-
|
21
|
-
|
18
|
+
@config.log.additional_context = { ranking_scoring_id: }
|
19
|
+
@reviewers = generate_reviewers
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
21
|
+
players_without_score.each do |player|
|
22
|
+
player.score = generate_score(player)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
@@ -40,7 +37,7 @@ module ActiveGenie
|
|
40
37
|
config: @config
|
41
38
|
).values_at('final_score', 'final_reasoning')
|
42
39
|
|
43
|
-
|
40
|
+
@config.logger.call({ code: :new_score, player_id: player.id, score:, reasoning: })
|
44
41
|
|
45
42
|
score
|
46
43
|
end
|
@@ -54,20 +51,18 @@ module ActiveGenie
|
|
54
51
|
config: @config
|
55
52
|
).values_at('reviewer1', 'reviewer2', 'reviewer3')
|
56
53
|
|
57
|
-
|
54
|
+
@config.logger.call({ code: :new_reviewers, reviewers: [reviewer1, reviewer2, reviewer3] })
|
58
55
|
|
59
56
|
[reviewer1, reviewer2, reviewer3]
|
60
57
|
end
|
61
58
|
|
62
|
-
def log_context
|
63
|
-
{ ranking_scoring_id: }
|
64
|
-
end
|
65
|
-
|
66
59
|
def ranking_scoring_id
|
67
|
-
|
68
|
-
|
60
|
+
@ranking_scoring_id ||= begin
|
61
|
+
player_ids = players_without_score.map(&:id).join(',')
|
62
|
+
ranking_unique_key = [player_ids, @criteria, @config.to_json].join('-')
|
69
63
|
|
70
|
-
|
64
|
+
"#{Digest::MD5.hexdigest(ranking_unique_key)}-scoring"
|
65
|
+
end
|
71
66
|
end
|
72
67
|
end
|
73
68
|
end
|
@@ -52,19 +52,19 @@ module ActiveGenie
|
|
52
52
|
|
53
53
|
result['final_score'] = 0 if result['final_score'].nil?
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
@config.logger.call({
|
56
|
+
code: :scoring,
|
57
|
+
text: @text[0..30],
|
58
|
+
criteria: @criteria[0..30],
|
59
|
+
reviewers: reviewers,
|
60
|
+
score: result['final_score'],
|
61
|
+
reasoning: result['final_reasoning']
|
62
|
+
})
|
63
63
|
|
64
64
|
result
|
65
65
|
end
|
66
66
|
|
67
|
-
PROMPT = File.read(File.join(__dir__, 'generalist.md'))
|
67
|
+
PROMPT = File.read(File.join(__dir__, 'generalist.prompt.md'))
|
68
68
|
|
69
69
|
private
|
70
70
|
|
@@ -7,7 +7,7 @@ ActiveGenie.configure do |config|
|
|
7
7
|
# config.providers.openai.api_url = 'https://api.openai.com/v1'
|
8
8
|
# config.providers.openai.lower_tier_model = 'gpt-4.1-mini'
|
9
9
|
# config.providers.openai.middle_tier_model = 'gpt-4.1'
|
10
|
-
# config.providers.openai.
|
10
|
+
# config.providers.openai.higher_tier_model = 'o3-mini'
|
11
11
|
# config.providers.openai.client = ActiveGenie::Providers::Openai::Client.new(config)
|
12
12
|
|
13
13
|
# example how add a new provider
|
metadata
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_genie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.27.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radamés Roriz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
|
-
|
15
|
-
|
16
|
-
ActiveGenie is a Ruby gem that provides valuable solutions using GenAI. Just like Lodash or ActiveStorage, ActiveGenie brings a set of Modules to reach real value fast and reliably. Backed by a custom benchmarking system that ensures consistent quality and performance across different models and providers in every release.
|
14
|
+
ActiveGenie is a Ruby gem that helps developers build reliable, future-proof GenAI features without worrying about changing models, prompts, or providers. Like Lodash for GenAI, it offers simple, reusable modules for tasks like data extraction, scoring, and ranking, so you can focus on your app’s logic, not the shifting AI landscape.
|
15
|
+
Behind the scenes, a custom benchmarking system keeps everything consistent across LLM vendors and versions, release after release.
|
17
16
|
email:
|
18
17
|
- radames@roriz.dev
|
19
18
|
executables: []
|
@@ -27,7 +26,7 @@ files:
|
|
27
26
|
- lib/active_genie/battle.rb
|
28
27
|
- lib/active_genie/battle/README.md
|
29
28
|
- lib/active_genie/battle/generalist.json
|
30
|
-
- lib/active_genie/battle/generalist.md
|
29
|
+
- lib/active_genie/battle/generalist.prompt.md
|
31
30
|
- lib/active_genie/battle/generalist.rb
|
32
31
|
- lib/active_genie/clients/providers/anthropic_client.rb
|
33
32
|
- lib/active_genie/clients/providers/base_client.rb
|
@@ -49,18 +48,15 @@ files:
|
|
49
48
|
- lib/active_genie/config/scoring_config.rb
|
50
49
|
- lib/active_genie/configuration.rb
|
51
50
|
- lib/active_genie/data_extractor.rb
|
52
|
-
- lib/active_genie/data_extractor/README.md
|
53
51
|
- lib/active_genie/data_extractor/from_informal.json
|
54
52
|
- lib/active_genie/data_extractor/from_informal.rb
|
55
53
|
- lib/active_genie/data_extractor/generalist.json
|
56
|
-
- lib/active_genie/data_extractor/generalist.md
|
54
|
+
- lib/active_genie/data_extractor/generalist.prompt.md
|
57
55
|
- lib/active_genie/data_extractor/generalist.rb
|
58
56
|
- lib/active_genie/errors/invalid_log_output_error.rb
|
59
57
|
- lib/active_genie/errors/invalid_provider_error.rb
|
60
58
|
- lib/active_genie/logger.rb
|
61
59
|
- lib/active_genie/ranking.rb
|
62
|
-
- lib/active_genie/ranking/README.md
|
63
|
-
- lib/active_genie/ranking/concerns/loggable.rb
|
64
60
|
- lib/active_genie/ranking/elo_round.rb
|
65
61
|
- lib/active_genie/ranking/free_for_all.rb
|
66
62
|
- lib/active_genie/ranking/player.rb
|
@@ -68,9 +64,8 @@ files:
|
|
68
64
|
- lib/active_genie/ranking/ranking.rb
|
69
65
|
- lib/active_genie/ranking/ranking_scoring.rb
|
70
66
|
- lib/active_genie/scoring.rb
|
71
|
-
- lib/active_genie/scoring/README.md
|
72
67
|
- lib/active_genie/scoring/generalist.json
|
73
|
-
- lib/active_genie/scoring/generalist.md
|
68
|
+
- lib/active_genie/scoring/generalist.prompt.md
|
74
69
|
- lib/active_genie/scoring/generalist.rb
|
75
70
|
- lib/active_genie/scoring/recommended_reviewers.rb
|
76
71
|
- lib/tasks/benchmark.rake
|
@@ -103,5 +98,5 @@ requirements: []
|
|
103
98
|
rubygems_version: 3.4.20
|
104
99
|
signing_key:
|
105
100
|
specification_version: 4
|
106
|
-
summary:
|
101
|
+
summary: 'The Lodash for GenAI: Real Value + Consistent + Model-Agnostic'
|
107
102
|
test_files: []
|