active_genie 0.30.3 → 0.30.8

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -5
  3. data/VERSION +1 -1
  4. data/lib/active_genie/comparator/debate.rb +13 -36
  5. data/lib/active_genie/comparator/fight.rb +3 -3
  6. data/lib/active_genie/comparator.rb +0 -2
  7. data/lib/active_genie/configs/base_config.rb +25 -0
  8. data/lib/active_genie/configs/extractor_config.rb +6 -14
  9. data/lib/active_genie/configs/lister_config.rb +6 -10
  10. data/lib/active_genie/configs/llm_config.rb +12 -26
  11. data/lib/active_genie/configs/log_config.rb +19 -16
  12. data/lib/active_genie/configs/providers/anthropic_config.rb +16 -1
  13. data/lib/active_genie/configs/providers/deepseek_config.rb +8 -2
  14. data/lib/active_genie/configs/providers/google_config.rb +8 -2
  15. data/lib/active_genie/configs/providers/openai_config.rb +8 -2
  16. data/lib/active_genie/configs/providers/provider_base.rb +22 -31
  17. data/lib/active_genie/configs/providers_config.rb +35 -16
  18. data/lib/active_genie/configs/ranker_config.rb +6 -12
  19. data/lib/active_genie/configuration.rb +23 -60
  20. data/lib/active_genie/{ranker/entities → entities}/player.rb +4 -0
  21. data/lib/active_genie/{ranker/entities → entities}/players.rb +1 -1
  22. data/lib/active_genie/entities/result.rb +29 -0
  23. data/lib/active_genie/errors/provider_server_error.rb +8 -5
  24. data/lib/active_genie/errors/without_available_provider_error.rb +39 -0
  25. data/lib/active_genie/extractor/data.json +9 -0
  26. data/lib/active_genie/extractor/data.prompt.md +12 -0
  27. data/lib/active_genie/extractor/data.rb +71 -0
  28. data/lib/active_genie/extractor/explanation.rb +19 -47
  29. data/lib/active_genie/extractor/litote.rb +8 -14
  30. data/lib/active_genie/extractor.rb +5 -0
  31. data/lib/active_genie/lister/feud.json +5 -1
  32. data/lib/active_genie/lister/feud.rb +10 -24
  33. data/lib/active_genie/lister/juries.rb +14 -20
  34. data/lib/active_genie/logger.rb +16 -28
  35. data/lib/active_genie/providers/anthropic_provider.rb +11 -5
  36. data/lib/active_genie/providers/base_provider.rb +15 -17
  37. data/lib/active_genie/providers/deepseek_provider.rb +17 -9
  38. data/lib/active_genie/providers/google_provider.rb +10 -4
  39. data/lib/active_genie/providers/openai_provider.rb +6 -4
  40. data/lib/active_genie/providers/unified_provider.rb +47 -17
  41. data/lib/active_genie/ranker/elo.rb +41 -36
  42. data/lib/active_genie/ranker/free_for_all.rb +45 -28
  43. data/lib/active_genie/ranker/scoring.rb +20 -11
  44. data/lib/active_genie/ranker/tournament.rb +23 -35
  45. data/lib/active_genie/scorer/jury_bench.rb +15 -29
  46. data/lib/active_genie/utils/base_module.rb +34 -0
  47. data/lib/active_genie/utils/call_wrapper.rb +20 -0
  48. data/lib/active_genie/utils/deep_merge.rb +12 -0
  49. data/lib/active_genie/utils/fiber_by_batch.rb +2 -2
  50. data/lib/active_genie/utils/text_case.rb +18 -0
  51. data/lib/active_genie.rb +16 -18
  52. data/lib/tasks/test.rake +61 -3
  53. metadata +19 -8
  54. data/lib/active_genie/configs/comparator_config.rb +0 -10
  55. data/lib/active_genie/configs/scorer_config.rb +0 -10
@@ -12,14 +12,12 @@ module ActiveGenie
12
12
  def initialize(players, criteria, juries: [], config: nil)
13
13
  @players = Entities::Players.new(players)
14
14
  @criteria = criteria
15
- @config = ActiveGenie.configuration.merge(config)
15
+ @initial_config = config
16
16
  @juries = Array(juries).compact.uniq
17
17
  end
18
18
 
19
19
  def call
20
- @config.log.additional_context = { ranker_scoring_id: }
21
-
22
- ActiveGenie::FiberByBatch.call(players_without_score, config: @config) do |player|
20
+ ActiveGenie::FiberByBatch.call(players_without_score, config:) do |player|
23
21
  player.score = generate_score(player)
24
22
  end
25
23
  end
@@ -31,14 +29,16 @@ module ActiveGenie
31
29
  end
32
30
 
33
31
  def generate_score(player)
34
- score, reasoning = ActiveGenie::Scorer.by_jury_bench(
32
+ result = ActiveGenie::Scorer.by_jury_bench(
35
33
  player.content,
36
34
  @criteria,
37
35
  @juries,
38
- config: @config
39
- ).values_at('final_score', 'final_reasoning')
36
+ config:
37
+ )
38
+ score = result.data.to_i
39
+ reasoning = result.reasoning
40
40
 
41
- @config.logger.call({ code: :new_score, player_id: player.id, score:, reasoning: })
41
+ ActiveGenie.logger.call({ code: :new_score, player_id: player.id, score:, reasoning: }, config:)
42
42
 
43
43
  score
44
44
  end
@@ -48,9 +48,9 @@ module ActiveGenie
48
48
  response = ActiveGenie::Lister.juries(
49
49
  [@players.sample.content, @players.sample.content].join("\n\n"),
50
50
  @criteria,
51
- config: @config
51
+ config:
52
52
  )
53
- @config.logger.call({ code: :new_juries, juries: response })
53
+ ActiveGenie.logger.call({ code: :new_juries, juries: response }, config:)
54
54
  response
55
55
  end
56
56
  end
@@ -58,11 +58,20 @@ module ActiveGenie
58
58
  def ranker_scoring_id
59
59
  @ranker_scoring_id ||= begin
60
60
  player_ids = players_without_score.map(&:id).join(',')
61
- ranker_unique_key = [player_ids, @criteria, @config.to_json].join('-')
61
+ ranker_unique_key = [player_ids, @criteria].join('-')
62
62
 
63
63
  "#{Digest::MD5.hexdigest(ranker_unique_key)}-scoring"
64
64
  end
65
65
  end
66
+
67
+ def config
68
+ @config ||= ActiveGenie.new_configuration(
69
+ DeepMerge.call(
70
+ @initial_config,
71
+ { log: { additional_context: { ranker_scoring_id: } } }
72
+ )
73
+ )
74
+ end
66
75
  end
67
76
  end
68
77
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'entities/players'
3
+ require_relative '../entities/players'
4
4
  require_relative 'free_for_all'
5
5
  require_relative 'elo'
6
6
  require_relative 'scoring'
@@ -30,33 +30,30 @@ require_relative 'scoring'
30
30
  # @return [Hash] Final ranked player results
31
31
  module ActiveGenie
32
32
  module Ranker
33
- class Tournament
34
- def self.call(...)
35
- new(...).call
36
- end
37
-
33
+ class Tournament < ActiveGenie::BaseModule
38
34
  def initialize(players, criteria, juries: [], config: {})
39
35
  @players = Entities::Players.new(players)
40
36
  @criteria = criteria
41
37
  @juries = Array(juries).compact.uniq
42
- @config = ActiveGenie.configuration.merge(config)
38
+ super(config:)
43
39
  end
44
40
 
45
41
  def call
46
- @config.log.additional_context = { ranker_id: }
47
-
48
42
  set_initial_player_scores!
49
43
  eliminate_obvious_bad_players!
50
44
 
51
45
  while @players.elo_eligible?
52
- elo_report = run_elo_round!
46
+ elo_result = run_elo_round!
53
47
  eliminate_lower_tier_players!
54
- rebalance_players!(elo_report)
48
+ rebalance_players!(elo_result)
55
49
  end
56
50
 
57
51
  run_free_for_all!
58
52
 
59
- sorted_players
53
+ ActiveGenie::Result.new(
54
+ data: sorted_players.map(&:content),
55
+ metadata: @players.map(&:to_h)
56
+ )
60
57
  end
61
58
 
62
59
  ELIMINATION_VARIATION = 'variation_too_high'
@@ -65,12 +62,7 @@ module ActiveGenie
65
62
  private
66
63
 
67
64
  def set_initial_player_scores!
68
- Scoring.call(
69
- @players,
70
- @criteria,
71
- juries: @juries,
72
- config: @config
73
- )
65
+ Scoring.call(@players, @criteria, juries: @juries, config:)
74
66
  end
75
67
 
76
68
  def eliminate_obvious_bad_players!
@@ -80,50 +72,46 @@ module ActiveGenie
80
72
  end
81
73
 
82
74
  def run_elo_round!
83
- Elo.call(
84
- @players,
85
- @criteria,
86
- config: @config
87
- )
75
+ Elo.call(@players, @criteria, config:)
88
76
  end
89
77
 
90
78
  def eliminate_lower_tier_players!
91
79
  @players.calc_lower_tier.each { |player| player.eliminated = ELIMINATION_RELEGATION }
92
80
  end
93
81
 
94
- def rebalance_players!(elo_report)
95
- return if elo_report[:highest_elo_diff].negative?
82
+ def rebalance_players!(elo_result)
83
+ return if elo_result.metadata[:highest_elo_diff].negative?
96
84
 
97
85
  @players.eligible.each do |player|
98
- next if elo_report[:players_in_round].include?(player.id)
86
+ next if elo_result.metadata[:players_in_round].include?(player.id)
99
87
 
100
- player.elo += elo_report[:highest_elo_diff]
88
+ player.elo += elo_result.metadata[:highest_elo_diff]
101
89
  end
102
90
  end
103
91
 
104
92
  def run_free_for_all!
105
- FreeForAll.call(
106
- @players,
107
- @criteria,
108
- config: @config
109
- )
93
+ FreeForAll.call(@players, @criteria, config:)
110
94
  end
111
95
 
112
96
  def sorted_players
113
97
  players = @players.sorted
114
- @config.logger.call({ ranker_id:, code: :ranker_final, players: players.map(&:to_h) })
98
+ ActiveGenie.logger.call({ ranker_id:, code: :ranker_final, players: players.map(&:to_h) }, config:)
115
99
 
116
- players.map(&:to_h)
100
+ players
117
101
  end
118
102
 
119
103
  def ranker_id
120
104
  @ranker_id ||= begin
121
105
  player_ids = @players.map(&:id).join(',')
122
- ranker_unique_key = [player_ids, @criteria, @config.to_json].join('-')
106
+ ranker_unique_key = [player_ids, @criteria].join('-')
123
107
 
124
108
  Digest::MD5.hexdigest(ranker_unique_key)
125
109
  end
126
110
  end
111
+
112
+ def module_config
113
+ { log: { additional_context: { ranker_id: } } }
114
+ end
127
115
  end
128
116
  end
129
117
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../providers/unified_provider'
4
+ require_relative '../utils/text_case'
4
5
 
5
6
  module ActiveGenie
6
7
  module Scorer
@@ -17,7 +18,7 @@ module ActiveGenie
17
18
  # @example Usage with automatic jury recommendation
18
19
  # JuryBench.call("Sample text", "Evaluate technical accuracy")
19
20
  #
20
- class JuryBench
21
+ class JuryBench < ActiveGenie::BaseModule
21
22
  # @param text [String] The text content to be evaluated
22
23
  # @param criteria [String] The evaluation criteria or rubric to assess against
23
24
  # @param juries [Array<String>] Optional list of specific juries. If empty,
@@ -26,15 +27,11 @@ module ActiveGenie
26
27
  # @return [Hash] The evaluation result containing the scores and reasoning
27
28
  # @return [Number] :final_score The final score of the text based on the criteria and juries
28
29
  # @return [String] :final_reasoning Detailed explanation of why the final score was reached
29
- def self.call(...)
30
- new(...).call
31
- end
32
-
33
30
  def initialize(text, criteria, juries = [], config: {})
34
31
  @text = text
35
32
  @criteria = criteria
36
33
  @param_juries = Array(juries).compact.uniq
37
- @initial_config = config
34
+ super(config:)
38
35
  end
39
36
 
40
37
  def call
@@ -44,24 +41,17 @@ module ActiveGenie
44
41
  { role: 'user', content: "Text to score: #{@text}" }
45
42
  ]
46
43
 
47
- result = ::ActiveGenie::Providers::UnifiedProvider.function_calling(
44
+ provider_response = ::ActiveGenie::Providers::UnifiedProvider.function_calling(
48
45
  messages,
49
46
  build_function,
50
47
  config:
51
48
  )
52
49
 
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
50
+ ActiveGenie::Result.new(
51
+ data: provider_response['final_score'] || 0,
52
+ reasoning: provider_response['final_reasoning'],
53
+ metadata: provider_response
54
+ )
65
55
  end
66
56
 
67
57
  PROMPT = File.read(File.join(__dir__, 'jury_bench.prompt.md'))
@@ -84,11 +74,12 @@ module ActiveGenie
84
74
  @properties ||= begin
85
75
  tmp = {}
86
76
  juries.each do |jury|
87
- tmp["#{jury}_reasoning"] = {
77
+ jury_key = ActiveGenie::TextCase.underscore(jury)
78
+ tmp["#{jury_key}_reasoning"] = {
88
79
  type: 'string',
89
80
  description: "The reasoning of the Scorer process by #{jury}."
90
81
  }
91
- tmp["#{jury}_score"] = {
82
+ tmp["#{jury_key}_score"] = {
92
83
  type: 'number',
93
84
  description: "The score given by #{jury}.",
94
85
  min: 0,
@@ -113,17 +104,12 @@ module ActiveGenie
113
104
  @juries ||= if @param_juries.any?
114
105
  @param_juries
115
106
  else
116
- ::ActiveGenie::Lister::Juries.call(@text, @criteria, config:)
107
+ ::ActiveGenie::Lister::Juries.call(@text, @criteria, config:).data
117
108
  end
118
109
  end
119
110
 
120
- def config
121
- @config ||= begin
122
- c = ActiveGenie.configuration.merge(@initial_config)
123
- c.llm.recommended_model = 'deepseek-chat' unless c.llm.recommended_model
124
-
125
- c
126
- end
111
+ def module_config
112
+ { llm: { recommended_model: 'deepseek-chat' } }
127
113
  end
128
114
  end
129
115
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'call_wrapper'
4
+
5
+ module ActiveGenie
6
+ class BaseModule
7
+ prepend CallWrapper
8
+
9
+ def self.call(...)
10
+ new(...).call
11
+ end
12
+
13
+ def initialize(config: {})
14
+ @initial_config = config || {}
15
+ end
16
+
17
+ def call
18
+ raise NotImplementedError, 'Subclasses must implement the `call` method'
19
+ end
20
+
21
+ def config
22
+ @config ||= ActiveGenie.new_configuration(
23
+ ActiveGenie::DeepMerge.call(
24
+ @initial_config.to_h,
25
+ module_config
26
+ )
27
+ )
28
+ end
29
+
30
+ def module_config
31
+ {}
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveGenie
4
+ module CallWrapper
5
+ def call(*, &)
6
+ response = super # Call the original method
7
+
8
+ if defined?(config)
9
+ ActiveGenie.logger.call(
10
+ {
11
+ code: self.class.name,
12
+ response: response.to_h
13
+ }, config:
14
+ )
15
+ end
16
+
17
+ response
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveGenie
4
+ module DeepMerge
5
+ module_function
6
+
7
+ def call(first_hash, second_hash)
8
+ merger = proc { |_key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2 }
9
+ first_hash.to_h.merge(second_hash.to_h, &merger)
10
+ end
11
+ end
12
+ end
@@ -8,9 +8,9 @@ module ActiveGenie
8
8
 
9
9
  def call(items, config:, &block)
10
10
  items.each_slice(config.llm.max_fibers).to_a.each do |batch|
11
- Async do
11
+ Async do |task|
12
12
  tasks = batch.map do |item|
13
- Async { block.call(item) }
13
+ task.async { block.call(item) }
14
14
  end
15
15
 
16
16
  tasks.each(&:wait)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveGenie
4
+ module TextCase
5
+ module_function
6
+
7
+ def underscore(camel_cased_word)
8
+ return camel_cased_word.to_s.dup unless /[A-Z-]|::/.match?(camel_cased_word)
9
+
10
+ word = camel_cased_word.to_s.gsub('::', '/')
11
+ word.gsub!(/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z\d])(?=[A-Z])/, '_')
12
+ word.tr!('-', '_')
13
+ word.tr!(' ', '_')
14
+ word.downcase!
15
+ word
16
+ end
17
+ end
18
+ end
data/lib/active_genie.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  require_relative 'active_genie/logger'
4
4
  require_relative 'active_genie/configuration'
5
5
 
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'
6
+ require_relative 'active_genie/entities/result'
7
+ require_relative 'active_genie/utils/base_module'
8
+ require_relative 'active_genie/utils/deep_merge'
10
9
 
11
10
  module ActiveGenie
12
11
  autoload :Extractor, File.join(__dir__, 'active_genie/extractor')
@@ -23,27 +22,26 @@ module ActiveGenie
23
22
  end
24
23
 
25
24
  def configuration
26
- @configuration ||= initialize_configuration
25
+ @configuration ||= Configuration.new
27
26
  end
28
27
 
29
- def load_tasks
30
- return unless defined?(Rake)
28
+ def new_configuration(new_config)
29
+ return new_config if new_config.instance_of?(Configuration)
31
30
 
32
- Rake::Task.define_task(:environment)
33
- Dir.glob(File.join(__dir__, 'tasks', '*.rake')).each { |r| load r }
31
+ Configuration.new(
32
+ DeepMerge.call(@configuration.to_h, new_config)
33
+ )
34
34
  end
35
35
 
36
- private
37
-
38
- def initialize_configuration
39
- config = Configuration.new
36
+ def logger
37
+ @logger ||= Logger.new
38
+ end
40
39
 
41
- config.providers.add(Config::Providers::OpenaiConfig)
42
- config.providers.add(Config::Providers::GoogleConfig)
43
- config.providers.add(Config::Providers::AnthropicConfig)
44
- config.providers.add(Config::Providers::DeepseekConfig)
40
+ def load_tasks
41
+ return unless defined?(Rake)
45
42
 
46
- config
43
+ Rake::Task.define_task(:environment)
44
+ Dir.glob(File.join(__dir__, 'tasks', '*.rake')).each { |r| load r }
47
45
  end
48
46
  end
49
47
  end
data/lib/tasks/test.rake CHANGED
@@ -6,13 +6,71 @@ namespace :test do
6
6
  Rake::TestTask.new(:unit) do |t|
7
7
  t.pattern = 'test/unit/**/*_test.rb'
8
8
  end
9
+ desc 'Run unit tests'
10
+ task unit: :reset_env
9
11
 
10
12
  Rake::TestTask.new(:integration) do |t|
11
- t.pattern = 'test/integration/**/*_test.rb' # Or use _spec.rb for RSpec
13
+ t.pattern = 'test/integration/**/*_test.rb'
12
14
  end
15
+ desc 'Run integration tests like install rails'
16
+ task integration: :reset_env
13
17
 
18
+ desc 'Run all tests (unit and integration)'
14
19
  task default: %i[unit integration]
20
+
21
+ desc 'Reset environment variables for API keys'
22
+ task :reset_env do
23
+ reset_environment_variables
24
+ end
25
+ end
26
+
27
+ desc 'Run all tests (unit and integration) or a specific test file'
28
+ task :test, [:file_path] do |_t, args|
29
+ reset_environment_variables
30
+
31
+ if args[:file_path]
32
+ file_path, line_number = args[:file_path].split(':')
33
+
34
+ if line_number
35
+ test_name = find_test_name_at_line(file_path, line_number.to_i)
36
+
37
+ if test_name
38
+ sh "ruby -Itest #{file_path} --name #{test_name}"
39
+ else
40
+ puts "Warning: Could not find test method at line #{line_number}"
41
+ ruby "-Itest #{file_path}"
42
+ end
43
+ else
44
+ ruby "-Itest #{file_path}"
45
+ end
46
+ else
47
+ Rake::Task['test:unit'].invoke
48
+ Rake::Task['test:integration'].invoke
49
+ end
15
50
  end
16
51
 
17
- desc 'Run all tests (unit and integration)'
18
- task test: ['test:unit', 'test:integration']
52
+ def find_test_name_at_line(file_path, line_number)
53
+ return nil unless File.exist?(file_path)
54
+
55
+ lines = File.readlines(file_path)
56
+ return nil if line_number > lines.length
57
+
58
+ (line_number - 1).downto(0) do |i|
59
+ line = lines[i]
60
+ if line =~ /^\s*def\s+(test_\w+)/
61
+ return Regexp.last_match(1)
62
+ elsif line =~ /^\s*test\s+['"](.+?)['"]\s+do/
63
+ test_desc = Regexp.last_match(1)
64
+ return "/#{test_desc}/"
65
+ end
66
+ end
67
+
68
+ nil
69
+ end
70
+
71
+ def reset_environment_variables
72
+ ENV['OPENAI_API_KEY'] = nil
73
+ ENV['GEMINI_API_KEY'] = nil
74
+ ENV['ANTHROPIC_API_KEY'] = nil
75
+ ENV['DEEPSEEK_API_KEY'] = nil
76
+ 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.30.3
4
+ version: 0.30.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Radamés Roriz
@@ -24,8 +24,11 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '2.0'
26
26
  description: |
27
- 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 extractor, comparator, scorer, and ranker, so you can focus on your app’s logic, not the shifting AI landscape.
28
- Behind the scenes, a custom benchmarking system keeps everything consistent across LLM vendors and versions, release after release.
27
+ ActiveGenie is an enabler for creating reliable GenAI features, offering powerful, model-agnostic tools across any provider. It allows you to settle subjective comparisons with a `ActibeGenie::Comparator` module that stages a political debate, get accurate scores from an AI jury using `ActiveGenie::Scorer`, and rank large datasets using `ActiveGenie::Ranker`'s tournament-style system.
28
+ This reliability is built on three core pillars:
29
+ - Custom Benchmarking: Testing for consistency with every new version and model update.
30
+ - Reasoning Prompting: Utilizing human reasoning techniques (like debate and jury review) to control a model's reasoning.
31
+ - Overfitting Prompts: Highly specialized, and potentially model-specific, prompt for each module's purpose.
29
32
  email:
30
33
  - radames@roriz.dev
31
34
  executables: []
@@ -43,7 +46,7 @@ files:
43
46
  - lib/active_genie/comparator/fight.json
44
47
  - lib/active_genie/comparator/fight.prompt.md
45
48
  - lib/active_genie/comparator/fight.rb
46
- - lib/active_genie/configs/comparator_config.rb
49
+ - lib/active_genie/configs/base_config.rb
47
50
  - lib/active_genie/configs/extractor_config.rb
48
51
  - lib/active_genie/configs/lister_config.rb
49
52
  - lib/active_genie/configs/llm_config.rb
@@ -55,13 +58,19 @@ files:
55
58
  - lib/active_genie/configs/providers/provider_base.rb
56
59
  - lib/active_genie/configs/providers_config.rb
57
60
  - lib/active_genie/configs/ranker_config.rb
58
- - lib/active_genie/configs/scorer_config.rb
59
61
  - lib/active_genie/configuration.rb
62
+ - lib/active_genie/entities/player.rb
63
+ - lib/active_genie/entities/players.rb
64
+ - lib/active_genie/entities/result.rb
60
65
  - lib/active_genie/errors/invalid_log_output_error.rb
61
66
  - lib/active_genie/errors/invalid_model_error.rb
62
67
  - lib/active_genie/errors/invalid_provider_error.rb
63
68
  - lib/active_genie/errors/provider_server_error.rb
69
+ - lib/active_genie/errors/without_available_provider_error.rb
64
70
  - lib/active_genie/extractor.rb
71
+ - lib/active_genie/extractor/data.json
72
+ - lib/active_genie/extractor/data.prompt.md
73
+ - lib/active_genie/extractor/data.rb
65
74
  - lib/active_genie/extractor/explanation.json
66
75
  - lib/active_genie/extractor/explanation.prompt.md
67
76
  - lib/active_genie/extractor/explanation.rb
@@ -82,15 +91,17 @@ files:
82
91
  - lib/active_genie/providers/unified_provider.rb
83
92
  - lib/active_genie/ranker.rb
84
93
  - lib/active_genie/ranker/elo.rb
85
- - lib/active_genie/ranker/entities/player.rb
86
- - lib/active_genie/ranker/entities/players.rb
87
94
  - lib/active_genie/ranker/free_for_all.rb
88
95
  - lib/active_genie/ranker/scoring.rb
89
96
  - lib/active_genie/ranker/tournament.rb
90
97
  - lib/active_genie/scorer.rb
91
98
  - lib/active_genie/scorer/jury_bench.prompt.md
92
99
  - lib/active_genie/scorer/jury_bench.rb
100
+ - lib/active_genie/utils/base_module.rb
101
+ - lib/active_genie/utils/call_wrapper.rb
102
+ - lib/active_genie/utils/deep_merge.rb
93
103
  - lib/active_genie/utils/fiber_by_batch.rb
104
+ - lib/active_genie/utils/text_case.rb
94
105
  - lib/tasks/benchmark.rake
95
106
  - lib/tasks/install.rake
96
107
  - lib/tasks/templates/active_genie.rb
@@ -120,5 +131,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
131
  requirements: []
121
132
  rubygems_version: 3.6.9
122
133
  specification_version: 4
123
- summary: 'The Lodash for GenAI: Real Value + Consistent + Model-Agnostic'
134
+ summary: 'The Lodash for GenAI: Consistent + Model-Agnostic'
124
135
  test_files: []
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveGenie
4
- module Config
5
- # rubocop:disable Lint/EmptyClass
6
- class ComparatorConfig
7
- end
8
- # rubocop:enable Lint/EmptyClass
9
- end
10
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveGenie
4
- module Config
5
- # rubocop:disable Lint/EmptyClass
6
- class ScorerConfig
7
- end
8
- # rubocop:enable Lint/EmptyClass
9
- end
10
- end