active_genie 0.29.1 → 0.30.0
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 +1 -1
- data/VERSION +1 -1
- data/lib/active_genie/{battle/generalist.json → comparator/debate.json} +2 -2
- data/lib/active_genie/{battle/generalist.prompt.md → comparator/debate.prompt.md} +1 -1
- data/lib/active_genie/{battle/generalist.rb → comparator/debate.rb} +20 -21
- data/lib/active_genie/{battle → comparator}/fight.rb +7 -7
- data/lib/active_genie/comparator.rb +24 -0
- data/lib/active_genie/{config/scoring_config.rb → configs/comparator_config.rb} +1 -1
- data/lib/active_genie/{config/data_extractor_config.rb → configs/extractor_config.rb} +1 -1
- data/lib/active_genie/{config/factory_config.rb → configs/lister_config.rb} +1 -1
- data/lib/active_genie/{config → configs}/llm_config.rb +6 -6
- data/lib/active_genie/{config/ranking_config.rb → configs/ranker_config.rb} +1 -1
- data/lib/active_genie/{config/battle_config.rb → configs/scorer_config.rb} +1 -1
- data/lib/active_genie/configuration.rb +19 -19
- data/lib/active_genie/errors/invalid_provider_error.rb +1 -1
- data/lib/active_genie/{data_extractor/generalist.rb → extractor/explanation.rb} +11 -11
- data/lib/active_genie/{data_extractor/from_informal.rb → extractor/litote.rb} +7 -7
- data/lib/active_genie/extractor.rb +22 -0
- data/lib/active_genie/{factory → lister}/feud.rb +6 -6
- data/lib/active_genie/lister/juries.prompt.md +20 -0
- data/lib/active_genie/lister/juries.rb +82 -0
- data/lib/active_genie/{factory.rb → lister.rb} +7 -6
- data/lib/active_genie/{clients/providers/anthropic_client.rb → providers/anthropic_provider.rb} +4 -4
- data/lib/active_genie/{clients/providers/base_client.rb → providers/base_provider.rb} +6 -6
- data/lib/active_genie/{clients/providers/deepseek_client.rb → providers/deepseek_provider.rb} +3 -3
- data/lib/active_genie/{clients/providers/google_client.rb → providers/google_provider.rb} +6 -6
- data/lib/active_genie/{clients/providers/openai_client.rb → providers/openai_provider.rb} +3 -3
- data/lib/active_genie/providers/unified_provider.rb +44 -0
- data/lib/active_genie/{ranking/elo_round.rb → ranker/elo.rb} +35 -35
- data/lib/active_genie/ranker/entities/player.rb +124 -0
- data/lib/active_genie/ranker/entities/players.rb +102 -0
- data/lib/active_genie/{ranking → ranker}/free_for_all.rb +8 -8
- data/lib/active_genie/ranker/scoring.rb +66 -0
- data/lib/active_genie/{ranking/ranking.rb → ranker/tournament.rb} +17 -25
- data/lib/active_genie/ranker.rb +32 -0
- data/lib/active_genie/scorer/jury_bench.rb +121 -0
- data/lib/active_genie/scorer.rb +17 -0
- data/lib/active_genie.rb +9 -9
- data/lib/tasks/test.rake +4 -0
- metadata +50 -50
- data/lib/active_genie/battle.rb +0 -31
- data/lib/active_genie/clients/unified_client.rb +0 -50
- data/lib/active_genie/data_extractor.rb +0 -23
- data/lib/active_genie/ranking/player.rb +0 -122
- data/lib/active_genie/ranking/players_collection.rb +0 -95
- data/lib/active_genie/ranking/ranking_scoring.rb +0 -69
- data/lib/active_genie/ranking.rb +0 -14
- data/lib/active_genie/scoring/generalist.json +0 -9
- data/lib/active_genie/scoring/generalist.rb +0 -119
- data/lib/active_genie/scoring/recommended_reviewers.rb +0 -87
- data/lib/active_genie/scoring.rb +0 -23
- /data/lib/active_genie/{battle → comparator}/fight.json +0 -0
- /data/lib/active_genie/{battle → comparator}/fight.prompt.md +0 -0
- /data/lib/active_genie/{config → configs}/log_config.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers/anthropic_config.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers/deepseek_config.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers/google_config.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers/openai_config.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers/provider_base.rb +0 -0
- /data/lib/active_genie/{config → configs}/providers_config.rb +0 -0
- /data/lib/active_genie/{data_extractor/generalist.json → extractor/explanation.json} +0 -0
- /data/lib/active_genie/{data_extractor/generalist.prompt.md → extractor/explanation.prompt.md} +0 -0
- /data/lib/active_genie/{data_extractor/from_informal.json → extractor/litote.json} +0 -0
- /data/lib/active_genie/{factory → lister}/feud.json +0 -0
- /data/lib/active_genie/{factory → lister}/feud.prompt.md +0 -0
- /data/lib/active_genie/{scoring/generalist.prompt.md → scorer/jury_bench.md} +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'entities/players'
|
4
4
|
require_relative 'free_for_all'
|
5
|
-
require_relative '
|
6
|
-
require_relative '
|
5
|
+
require_relative 'elo'
|
6
|
+
require_relative 'scoring'
|
7
7
|
|
8
8
|
# This class orchestrates player ranking through multiple evaluation stages
|
9
9
|
# using Elo ranking and free-for-all match simulations.
|
@@ -13,7 +13,7 @@ require_relative 'ranking_scoring'
|
|
13
13
|
# 4. Conducts free-for-all matches
|
14
14
|
#
|
15
15
|
# @example Basic usage
|
16
|
-
#
|
16
|
+
# Ranker.tournament(players, criteria)
|
17
17
|
#
|
18
18
|
# @param param_players [Array<Hash|String>] Collection of player objects to evaluate
|
19
19
|
# Example: ["Circle", "Triangle", "Square"]
|
@@ -29,14 +29,14 @@ require_relative 'ranking_scoring'
|
|
29
29
|
# Example: { model: "gpt-4o", api_key: ENV['OPENAI_API_KEY'] }
|
30
30
|
# @return [Hash] Final ranked player results
|
31
31
|
module ActiveGenie
|
32
|
-
module
|
33
|
-
class
|
32
|
+
module Ranker
|
33
|
+
class Tournament
|
34
34
|
def self.call(...)
|
35
35
|
new(...).call
|
36
36
|
end
|
37
37
|
|
38
|
-
def initialize(
|
39
|
-
@
|
38
|
+
def initialize(players, criteria, reviewers: [], config: {})
|
39
|
+
@players = Players.new(players)
|
40
40
|
@criteria = criteria
|
41
41
|
@reviewers = Array(reviewers).compact.uniq
|
42
42
|
@config = ActiveGenie.configuration.merge(config)
|
@@ -44,8 +44,7 @@ module ActiveGenie
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def call
|
47
|
-
@
|
48
|
-
@config.log.additional_context = { ranking_id: }
|
47
|
+
@config.log.additional_context = { ranker_id: }
|
49
48
|
|
50
49
|
set_initial_player_scores!
|
51
50
|
eliminate_obvious_bad_players!
|
@@ -66,15 +65,8 @@ module ActiveGenie
|
|
66
65
|
|
67
66
|
private
|
68
67
|
|
69
|
-
def create_players
|
70
|
-
players = PlayersCollection.new(@param_players)
|
71
|
-
players.each { |p| @config.logger.call({ code: :new_player, player: p.to_h }) }
|
72
|
-
|
73
|
-
players
|
74
|
-
end
|
75
|
-
|
76
68
|
def set_initial_player_scores!
|
77
|
-
|
69
|
+
Scoring.call(
|
78
70
|
@players,
|
79
71
|
@criteria,
|
80
72
|
reviewers: @reviewers,
|
@@ -83,13 +75,13 @@ module ActiveGenie
|
|
83
75
|
end
|
84
76
|
|
85
77
|
def eliminate_obvious_bad_players!
|
86
|
-
while @players.coefficient_of_variation >= @config.
|
78
|
+
while @players.coefficient_of_variation >= @config.ranker.score_variation_threshold
|
87
79
|
@players.eligible.last.eliminated = ELIMINATION_VARIATION
|
88
80
|
end
|
89
81
|
end
|
90
82
|
|
91
83
|
def run_elo_round!
|
92
|
-
|
84
|
+
Elo.call(
|
93
85
|
@players,
|
94
86
|
@criteria,
|
95
87
|
config: @config
|
@@ -120,17 +112,17 @@ module ActiveGenie
|
|
120
112
|
|
121
113
|
def sorted_players
|
122
114
|
players = @players.sorted
|
123
|
-
@config.logger.call({
|
115
|
+
@config.logger.call({ ranker_id:, code: :ranker_final, players: players.map(&:to_h) })
|
124
116
|
|
125
117
|
players.map(&:to_h)
|
126
118
|
end
|
127
119
|
|
128
|
-
def
|
129
|
-
@
|
120
|
+
def ranker_id
|
121
|
+
@ranker_id ||= begin
|
130
122
|
player_ids = @players.map(&:id).join(',')
|
131
|
-
|
123
|
+
ranker_unique_key = [player_ids, @criteria, @config.to_json].join('-')
|
132
124
|
|
133
|
-
Digest::MD5.hexdigest(
|
125
|
+
Digest::MD5.hexdigest(ranker_unique_key)
|
134
126
|
end
|
135
127
|
end
|
136
128
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ranker/tournament'
|
4
|
+
require_relative 'ranker/free_for_all'
|
5
|
+
require_relative 'ranker/elo'
|
6
|
+
require_relative 'ranker/scoring'
|
7
|
+
|
8
|
+
module ActiveGenie
|
9
|
+
module Ranker
|
10
|
+
module_function
|
11
|
+
|
12
|
+
def call(...)
|
13
|
+
Tournament.call(...)
|
14
|
+
end
|
15
|
+
|
16
|
+
def by_tournament(...)
|
17
|
+
Tournament.call(...)
|
18
|
+
end
|
19
|
+
|
20
|
+
def by_free_for_all(...)
|
21
|
+
FreeForAll.call(...)
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_elo(...)
|
25
|
+
Elo.call(...)
|
26
|
+
end
|
27
|
+
|
28
|
+
def by_scoring(...)
|
29
|
+
Scoring.call(...)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../clients/unified_client'
|
4
|
+
|
5
|
+
module ActiveGenie
|
6
|
+
module Scorer
|
7
|
+
# The JuryBench class provides a foundation for Scorer text content against specified criteria
|
8
|
+
# using AI-powered evaluation. It supports both single and multiple jury scenarios,
|
9
|
+
# with the ability to automatically recommend juries when none are specified.
|
10
|
+
#
|
11
|
+
# The Scorer process evaluates text based on given criteria and returns detailed feedback
|
12
|
+
# including individual jury scores, reasoning, and a final aggregated score.
|
13
|
+
#
|
14
|
+
# @example JuryBench usage with a single jury
|
15
|
+
# JuryBench.call("Sample text", "Evaluate grammar and clarity", ["Grammar Expert"])
|
16
|
+
#
|
17
|
+
# @example Usage with automatic jury recommendation
|
18
|
+
# JuryBench.call("Sample text", "Evaluate technical accuracy")
|
19
|
+
#
|
20
|
+
class JuryBench
|
21
|
+
# @param text [String] The text content to be evaluated
|
22
|
+
# @param criteria [String] The evaluation criteria or rubric to assess against
|
23
|
+
# @param juries [Array<String>] Optional list of specific juries. If empty,
|
24
|
+
# juries will be automatically recommended based on the content and criteria
|
25
|
+
# @param config [Hash] Additional configuration config that modify the Scorer behavior
|
26
|
+
# @return [Hash] The evaluation result containing the scores and reasoning
|
27
|
+
# @return [Number] :final_score The final score of the text based on the criteria and juries
|
28
|
+
# @return [String] :final_reasoning Detailed explanation of why the final score was reached
|
29
|
+
def self.call(...)
|
30
|
+
new(...).call
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(text, criteria, juries = [], config: {})
|
34
|
+
@text = text
|
35
|
+
@criteria = criteria
|
36
|
+
@param_juries = Array(juries).compact.uniq
|
37
|
+
@config = ActiveGenie.configuration.merge(config)
|
38
|
+
end
|
39
|
+
|
40
|
+
def call
|
41
|
+
messages = [
|
42
|
+
{ role: 'system', content: PROMPT },
|
43
|
+
{ role: 'user', content: "Scorer criteria: #{@criteria}" },
|
44
|
+
{ role: 'user', content: "Text to score: #{@text}" }
|
45
|
+
]
|
46
|
+
|
47
|
+
result = ::ActiveGenie::Clients::UnifiedClient.function_calling(
|
48
|
+
messages,
|
49
|
+
build_function,
|
50
|
+
config: @config
|
51
|
+
)
|
52
|
+
|
53
|
+
result['final_score'] = 0 if result['final_score'].nil?
|
54
|
+
|
55
|
+
@config.logger.call({
|
56
|
+
code: :Scorer,
|
57
|
+
text: @text[0..30],
|
58
|
+
criteria: @criteria[0..30],
|
59
|
+
juries: juries,
|
60
|
+
score: result['final_score'],
|
61
|
+
reasoning: result['final_reasoning']
|
62
|
+
})
|
63
|
+
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
PROMPT = File.read(File.join(__dir__, 'jury_bench.prompt.md'))
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def build_function
|
72
|
+
{
|
73
|
+
name: 'scorer',
|
74
|
+
description: 'Score the text based on the given criteria.',
|
75
|
+
parameters: {
|
76
|
+
type: 'object',
|
77
|
+
properties: properties,
|
78
|
+
required: properties.keys
|
79
|
+
}
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def properties
|
84
|
+
@properties ||= begin
|
85
|
+
tmp = {}
|
86
|
+
juries.each do |jury|
|
87
|
+
tmp["#{jury}_reasoning"] = {
|
88
|
+
type: 'string',
|
89
|
+
description: "The reasoning of the Scorer process by #{jury}."
|
90
|
+
}
|
91
|
+
tmp["#{jury}_score"] = {
|
92
|
+
type: 'number',
|
93
|
+
description: "The score given by #{jury}.",
|
94
|
+
min: 0,
|
95
|
+
max: 100
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
tmp[:final_score] = {
|
100
|
+
type: 'number',
|
101
|
+
description: 'The final score based on the previous juries'
|
102
|
+
}
|
103
|
+
tmp[:final_reasoning] = {
|
104
|
+
type: 'string',
|
105
|
+
description: 'The final reasoning based on the previous juries'
|
106
|
+
}
|
107
|
+
|
108
|
+
tmp
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def juries
|
113
|
+
@juries ||= if @param_juries.any?
|
114
|
+
@param_juries
|
115
|
+
else
|
116
|
+
::ActiveGenie::Lister::Juries.call(@text, @criteria, config: @config)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'scorer/jury_bench'
|
4
|
+
|
5
|
+
module ActiveGenie
|
6
|
+
module Scorer
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def call(...)
|
10
|
+
JuryBench.call(...)
|
11
|
+
end
|
12
|
+
|
13
|
+
def by_jury_bench(...)
|
14
|
+
JuryBench.call(...)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/active_genie.rb
CHANGED
@@ -3,17 +3,17 @@
|
|
3
3
|
require_relative 'active_genie/logger'
|
4
4
|
require_relative 'active_genie/configuration'
|
5
5
|
|
6
|
-
require_relative 'active_genie/
|
7
|
-
require_relative 'active_genie/
|
8
|
-
require_relative 'active_genie/
|
9
|
-
require_relative 'active_genie/
|
6
|
+
require_relative 'active_genie/configs/providers/openai_config'
|
7
|
+
require_relative 'active_genie/configs/providers/google_config'
|
8
|
+
require_relative 'active_genie/configs/providers/anthropic_config'
|
9
|
+
require_relative 'active_genie/configs/providers/deepseek_config'
|
10
10
|
|
11
11
|
module ActiveGenie
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
12
|
+
autoload :Extractor, File.join(__dir__, 'active_genie/extractor')
|
13
|
+
autoload :Comparator, File.join(__dir__, 'active_genie/comparator')
|
14
|
+
autoload :Scorer, File.join(__dir__, 'active_genie/scorer')
|
15
|
+
autoload :Ranker, File.join(__dir__, 'active_genie/ranker')
|
16
|
+
autoload :Lister, File.join(__dir__, 'active_genie/lister')
|
17
17
|
|
18
18
|
VERSION = File.read(File.expand_path('../VERSION', __dir__)).strip
|
19
19
|
|
data/lib/tasks/test.rake
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
3
5
|
namespace :test do
|
4
6
|
Rake::TestTask.new(:unit) do |t|
|
5
7
|
t.pattern = 'test/unit/**/*_test.rb'
|
@@ -8,4 +10,6 @@ namespace :test do
|
|
8
10
|
Rake::TestTask.new(:integration) do |t|
|
9
11
|
t.pattern = 'test/integration/**/*_test.rb' # Or use _spec.rb for RSpec
|
10
12
|
end
|
13
|
+
|
14
|
+
task default: %i[unit integration]
|
11
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_genie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.30.0
|
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-08-
|
11
|
+
date: 2025-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
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.
|
@@ -23,58 +23,58 @@ files:
|
|
23
23
|
- README.md
|
24
24
|
- VERSION
|
25
25
|
- lib/active_genie.rb
|
26
|
-
- lib/active_genie/
|
27
|
-
- lib/active_genie/
|
28
|
-
- lib/active_genie/
|
29
|
-
- lib/active_genie/
|
30
|
-
- lib/active_genie/
|
31
|
-
- lib/active_genie/
|
32
|
-
- lib/active_genie/
|
33
|
-
- lib/active_genie/
|
34
|
-
- lib/active_genie/
|
35
|
-
- lib/active_genie/
|
36
|
-
- lib/active_genie/
|
37
|
-
- lib/active_genie/
|
38
|
-
- lib/active_genie/
|
39
|
-
- lib/active_genie/
|
40
|
-
- lib/active_genie/
|
41
|
-
- lib/active_genie/
|
42
|
-
- lib/active_genie/
|
43
|
-
- lib/active_genie/
|
44
|
-
- lib/active_genie/
|
45
|
-
- lib/active_genie/
|
46
|
-
- lib/active_genie/config/providers/google_config.rb
|
47
|
-
- lib/active_genie/config/providers/openai_config.rb
|
48
|
-
- lib/active_genie/config/providers/provider_base.rb
|
49
|
-
- lib/active_genie/config/providers_config.rb
|
50
|
-
- lib/active_genie/config/ranking_config.rb
|
51
|
-
- lib/active_genie/config/scoring_config.rb
|
26
|
+
- lib/active_genie/comparator.rb
|
27
|
+
- lib/active_genie/comparator/debate.json
|
28
|
+
- lib/active_genie/comparator/debate.prompt.md
|
29
|
+
- lib/active_genie/comparator/debate.rb
|
30
|
+
- lib/active_genie/comparator/fight.json
|
31
|
+
- lib/active_genie/comparator/fight.prompt.md
|
32
|
+
- lib/active_genie/comparator/fight.rb
|
33
|
+
- lib/active_genie/configs/comparator_config.rb
|
34
|
+
- lib/active_genie/configs/extractor_config.rb
|
35
|
+
- lib/active_genie/configs/lister_config.rb
|
36
|
+
- lib/active_genie/configs/llm_config.rb
|
37
|
+
- lib/active_genie/configs/log_config.rb
|
38
|
+
- lib/active_genie/configs/providers/anthropic_config.rb
|
39
|
+
- lib/active_genie/configs/providers/deepseek_config.rb
|
40
|
+
- lib/active_genie/configs/providers/google_config.rb
|
41
|
+
- lib/active_genie/configs/providers/openai_config.rb
|
42
|
+
- lib/active_genie/configs/providers/provider_base.rb
|
43
|
+
- lib/active_genie/configs/providers_config.rb
|
44
|
+
- lib/active_genie/configs/ranker_config.rb
|
45
|
+
- lib/active_genie/configs/scorer_config.rb
|
52
46
|
- lib/active_genie/configuration.rb
|
53
|
-
- lib/active_genie/data_extractor.rb
|
54
|
-
- lib/active_genie/data_extractor/from_informal.json
|
55
|
-
- lib/active_genie/data_extractor/from_informal.rb
|
56
|
-
- lib/active_genie/data_extractor/generalist.json
|
57
|
-
- lib/active_genie/data_extractor/generalist.prompt.md
|
58
|
-
- lib/active_genie/data_extractor/generalist.rb
|
59
47
|
- lib/active_genie/errors/invalid_log_output_error.rb
|
60
48
|
- lib/active_genie/errors/invalid_provider_error.rb
|
61
|
-
- lib/active_genie/
|
62
|
-
- lib/active_genie/
|
63
|
-
- lib/active_genie/
|
64
|
-
- lib/active_genie/
|
49
|
+
- lib/active_genie/extractor.rb
|
50
|
+
- lib/active_genie/extractor/explanation.json
|
51
|
+
- lib/active_genie/extractor/explanation.prompt.md
|
52
|
+
- lib/active_genie/extractor/explanation.rb
|
53
|
+
- lib/active_genie/extractor/litote.json
|
54
|
+
- lib/active_genie/extractor/litote.rb
|
55
|
+
- lib/active_genie/lister.rb
|
56
|
+
- lib/active_genie/lister/feud.json
|
57
|
+
- lib/active_genie/lister/feud.prompt.md
|
58
|
+
- lib/active_genie/lister/feud.rb
|
59
|
+
- lib/active_genie/lister/juries.prompt.md
|
60
|
+
- lib/active_genie/lister/juries.rb
|
65
61
|
- lib/active_genie/logger.rb
|
66
|
-
- lib/active_genie/
|
67
|
-
- lib/active_genie/
|
68
|
-
- lib/active_genie/
|
69
|
-
- lib/active_genie/
|
70
|
-
- lib/active_genie/
|
71
|
-
- lib/active_genie/
|
72
|
-
- lib/active_genie/
|
73
|
-
- lib/active_genie/
|
74
|
-
- lib/active_genie/
|
75
|
-
- lib/active_genie/
|
76
|
-
- lib/active_genie/
|
77
|
-
- lib/active_genie/scoring
|
62
|
+
- lib/active_genie/providers/anthropic_provider.rb
|
63
|
+
- lib/active_genie/providers/base_provider.rb
|
64
|
+
- lib/active_genie/providers/deepseek_provider.rb
|
65
|
+
- lib/active_genie/providers/google_provider.rb
|
66
|
+
- lib/active_genie/providers/openai_provider.rb
|
67
|
+
- lib/active_genie/providers/unified_provider.rb
|
68
|
+
- lib/active_genie/ranker.rb
|
69
|
+
- lib/active_genie/ranker/elo.rb
|
70
|
+
- lib/active_genie/ranker/entities/player.rb
|
71
|
+
- lib/active_genie/ranker/entities/players.rb
|
72
|
+
- lib/active_genie/ranker/free_for_all.rb
|
73
|
+
- lib/active_genie/ranker/scoring.rb
|
74
|
+
- lib/active_genie/ranker/tournament.rb
|
75
|
+
- lib/active_genie/scorer.rb
|
76
|
+
- lib/active_genie/scorer/jury_bench.md
|
77
|
+
- lib/active_genie/scorer/jury_bench.rb
|
78
78
|
- lib/tasks/benchmark.rake
|
79
79
|
- lib/tasks/install.rake
|
80
80
|
- lib/tasks/templates/active_genie.rb
|
data/lib/active_genie/battle.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'battle/generalist'
|
4
|
-
require_relative 'battle/fight'
|
5
|
-
|
6
|
-
module ActiveGenie
|
7
|
-
# See the [Battle README](lib/active_genie/battle/README.md) for more information.
|
8
|
-
module Battle
|
9
|
-
module_function
|
10
|
-
|
11
|
-
def generalist(...)
|
12
|
-
Generalist.call(...)
|
13
|
-
end
|
14
|
-
|
15
|
-
def call(...)
|
16
|
-
Generalist.call(...)
|
17
|
-
end
|
18
|
-
|
19
|
-
def battle(...)
|
20
|
-
Generalist.call(...)
|
21
|
-
end
|
22
|
-
|
23
|
-
def compare(...)
|
24
|
-
Generalist.call(...)
|
25
|
-
end
|
26
|
-
|
27
|
-
def fight(...)
|
28
|
-
Fight.call(...)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'providers/openai_client'
|
4
|
-
require_relative 'providers/anthropic_client'
|
5
|
-
require_relative 'providers/google_client'
|
6
|
-
require_relative 'providers/deepseek_client'
|
7
|
-
require_relative '../errors/invalid_provider_error'
|
8
|
-
|
9
|
-
module ActiveGenie
|
10
|
-
module Clients
|
11
|
-
class UnifiedClient
|
12
|
-
class InvalidProviderError < StandardError; end
|
13
|
-
|
14
|
-
class << self
|
15
|
-
PROVIDER_NAME_TO_CLIENT = {
|
16
|
-
openai: OpenaiClient,
|
17
|
-
anthropic: AnthropicClient,
|
18
|
-
google: GoogleClient,
|
19
|
-
deepseek: DeepseekClient
|
20
|
-
}.freeze
|
21
|
-
|
22
|
-
def function_calling(messages, function, config: {})
|
23
|
-
client = config.llm.client
|
24
|
-
|
25
|
-
unless client
|
26
|
-
provider_name = config.llm.provider || config.providers.default
|
27
|
-
client = PROVIDER_NAME_TO_CLIENT[provider_name.to_sym]
|
28
|
-
end
|
29
|
-
|
30
|
-
raise ActiveGenie::InvalidProviderError, provider_name if client.nil?
|
31
|
-
|
32
|
-
response = client.new(config).function_calling(messages, function)
|
33
|
-
|
34
|
-
normalize_response(response)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def normalize_response(response)
|
40
|
-
response.each do |key, value|
|
41
|
-
response[key] = nil if ['null', 'none', 'undefined', '', 'unknown',
|
42
|
-
'<unknown>'].include?(value.to_s.strip.downcase)
|
43
|
-
end
|
44
|
-
|
45
|
-
response
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'data_extractor/generalist'
|
4
|
-
require_relative 'data_extractor/from_informal'
|
5
|
-
|
6
|
-
module ActiveGenie
|
7
|
-
# See the [DataExtractor README](lib/active_genie/data_extractor/README.md) for more information.
|
8
|
-
module DataExtractor
|
9
|
-
module_function
|
10
|
-
|
11
|
-
def call(...)
|
12
|
-
Generalist.call(...)
|
13
|
-
end
|
14
|
-
|
15
|
-
def generalist(...)
|
16
|
-
Generalist.call(...)
|
17
|
-
end
|
18
|
-
|
19
|
-
def from_informal(...)
|
20
|
-
FromInformal.call(...)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,122 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'digest'
|
4
|
-
|
5
|
-
module ActiveGenie
|
6
|
-
module Ranking
|
7
|
-
class Player
|
8
|
-
def initialize(params)
|
9
|
-
@params = params.is_a?(String) ? { content: params } : params.dup
|
10
|
-
@params[:content] ||= @params
|
11
|
-
end
|
12
|
-
|
13
|
-
def content
|
14
|
-
@content ||= @params[:content]
|
15
|
-
end
|
16
|
-
|
17
|
-
def name
|
18
|
-
@name ||= @params[:name] || content[0..10]
|
19
|
-
end
|
20
|
-
|
21
|
-
def id
|
22
|
-
@id ||= @params[:id] || Digest::MD5.hexdigest(content.to_s)
|
23
|
-
end
|
24
|
-
|
25
|
-
def score
|
26
|
-
@score ||= @params[:score]
|
27
|
-
end
|
28
|
-
|
29
|
-
def elo
|
30
|
-
@elo = @elo || @params[:elo] || generate_elo_by_score
|
31
|
-
end
|
32
|
-
|
33
|
-
def ffa_win_count
|
34
|
-
@ffa_win_count ||= @params[:ffa_win_count] || 0
|
35
|
-
end
|
36
|
-
|
37
|
-
def ffa_lose_count
|
38
|
-
@ffa_lose_count ||= @params[:ffa_lose_count] || 0
|
39
|
-
end
|
40
|
-
|
41
|
-
def ffa_draw_count
|
42
|
-
@ffa_draw_count ||= @params[:ffa_draw_count] || 0
|
43
|
-
end
|
44
|
-
|
45
|
-
def eliminated
|
46
|
-
@eliminated ||= @params[:eliminated]
|
47
|
-
end
|
48
|
-
|
49
|
-
def score=(value)
|
50
|
-
@score = value
|
51
|
-
@elo = generate_elo_by_score
|
52
|
-
end
|
53
|
-
|
54
|
-
def elo=(value)
|
55
|
-
@elo = value || BASE_ELO
|
56
|
-
end
|
57
|
-
|
58
|
-
attr_writer :eliminated
|
59
|
-
|
60
|
-
def draw!
|
61
|
-
@ffa_draw_count += 1
|
62
|
-
end
|
63
|
-
|
64
|
-
def win!
|
65
|
-
@ffa_win_count += 1
|
66
|
-
end
|
67
|
-
|
68
|
-
def lose!
|
69
|
-
@ffa_lose_count += 1
|
70
|
-
end
|
71
|
-
|
72
|
-
def ffa_score
|
73
|
-
(ffa_win_count * 3) + ffa_draw_count
|
74
|
-
end
|
75
|
-
|
76
|
-
def sort_value
|
77
|
-
(ffa_score * 1_000_000) + ((elo || 0) * 100) + (score || 0)
|
78
|
-
end
|
79
|
-
|
80
|
-
def to_json(*_args)
|
81
|
-
to_h.to_json
|
82
|
-
end
|
83
|
-
|
84
|
-
def to_h
|
85
|
-
{
|
86
|
-
id:, name:, content:,
|
87
|
-
|
88
|
-
score:, elo:,
|
89
|
-
ffa_win_count:, ffa_lose_count:, ffa_draw_count:,
|
90
|
-
eliminated:, ffa_score:, sort_value:
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def method_missing(method_name, *args, &)
|
95
|
-
if method_name == :[] && args.size == 1
|
96
|
-
attr_name = args.first.to_sym
|
97
|
-
|
98
|
-
return send(attr_name) if respond_to?(attr_name)
|
99
|
-
|
100
|
-
return nil
|
101
|
-
|
102
|
-
end
|
103
|
-
|
104
|
-
super
|
105
|
-
end
|
106
|
-
|
107
|
-
def respond_to_missing?(method_name, include_private = false)
|
108
|
-
method_name == :[] || super
|
109
|
-
end
|
110
|
-
|
111
|
-
BASE_ELO = 1000
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def generate_elo_by_score
|
116
|
-
return BASE_ELO if @score.nil?
|
117
|
-
|
118
|
-
BASE_ELO + (@score - 50)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|