active_genie 0.29.0 → 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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/lib/active_genie/{battle/generalist.json → comparator/debate.json} +2 -2
  5. data/lib/active_genie/{battle/generalist.prompt.md → comparator/debate.prompt.md} +1 -1
  6. data/lib/active_genie/{battle/generalist.rb → comparator/debate.rb} +20 -21
  7. data/lib/active_genie/{battle → comparator}/fight.rb +7 -7
  8. data/lib/active_genie/comparator.rb +24 -0
  9. data/lib/active_genie/{config/scoring_config.rb → configs/comparator_config.rb} +1 -1
  10. data/lib/active_genie/{config/data_extractor_config.rb → configs/extractor_config.rb} +1 -1
  11. data/lib/active_genie/{config/factory_config.rb → configs/lister_config.rb} +1 -1
  12. data/lib/active_genie/{config → configs}/llm_config.rb +6 -6
  13. data/lib/active_genie/{config/ranking_config.rb → configs/ranker_config.rb} +1 -1
  14. data/lib/active_genie/{config/battle_config.rb → configs/scorer_config.rb} +1 -1
  15. data/lib/active_genie/configuration.rb +19 -19
  16. data/lib/active_genie/errors/invalid_provider_error.rb +1 -1
  17. data/lib/active_genie/{data_extractor/generalist.rb → extractor/explanation.rb} +11 -11
  18. data/lib/active_genie/{data_extractor/from_informal.rb → extractor/litote.rb} +7 -7
  19. data/lib/active_genie/extractor.rb +22 -0
  20. data/lib/active_genie/{factory → lister}/feud.rb +6 -6
  21. data/lib/active_genie/lister/juries.prompt.md +20 -0
  22. data/lib/active_genie/lister/juries.rb +82 -0
  23. data/lib/active_genie/{factory.rb → lister.rb} +7 -6
  24. data/lib/active_genie/{clients/providers/anthropic_client.rb → providers/anthropic_provider.rb} +4 -4
  25. data/lib/active_genie/{clients/providers/base_client.rb → providers/base_provider.rb} +6 -6
  26. data/lib/active_genie/{clients/providers/deepseek_client.rb → providers/deepseek_provider.rb} +3 -3
  27. data/lib/active_genie/{clients/providers/google_client.rb → providers/google_provider.rb} +6 -6
  28. data/lib/active_genie/{clients/providers/openai_client.rb → providers/openai_provider.rb} +3 -3
  29. data/lib/active_genie/providers/unified_provider.rb +44 -0
  30. data/lib/active_genie/{ranking/elo_round.rb → ranker/elo.rb} +35 -35
  31. data/lib/active_genie/ranker/entities/player.rb +124 -0
  32. data/lib/active_genie/ranker/entities/players.rb +102 -0
  33. data/lib/active_genie/{ranking → ranker}/free_for_all.rb +8 -8
  34. data/lib/active_genie/ranker/scoring.rb +66 -0
  35. data/lib/active_genie/{ranking/ranking.rb → ranker/tournament.rb} +17 -25
  36. data/lib/active_genie/ranker.rb +32 -0
  37. data/lib/active_genie/scorer/jury_bench.rb +121 -0
  38. data/lib/active_genie/scorer.rb +17 -0
  39. data/lib/active_genie.rb +9 -9
  40. data/lib/tasks/test.rake +15 -0
  41. metadata +51 -50
  42. data/lib/active_genie/battle.rb +0 -31
  43. data/lib/active_genie/clients/unified_client.rb +0 -50
  44. data/lib/active_genie/data_extractor.rb +0 -23
  45. data/lib/active_genie/ranking/player.rb +0 -122
  46. data/lib/active_genie/ranking/players_collection.rb +0 -95
  47. data/lib/active_genie/ranking/ranking_scoring.rb +0 -69
  48. data/lib/active_genie/ranking.rb +0 -14
  49. data/lib/active_genie/scoring/generalist.json +0 -9
  50. data/lib/active_genie/scoring/generalist.rb +0 -119
  51. data/lib/active_genie/scoring/recommended_reviewers.rb +0 -87
  52. data/lib/active_genie/scoring.rb +0 -23
  53. /data/lib/active_genie/{battle → comparator}/fight.json +0 -0
  54. /data/lib/active_genie/{battle → comparator}/fight.prompt.md +0 -0
  55. /data/lib/active_genie/{config → configs}/log_config.rb +0 -0
  56. /data/lib/active_genie/{config → configs}/providers/anthropic_config.rb +0 -0
  57. /data/lib/active_genie/{config → configs}/providers/deepseek_config.rb +0 -0
  58. /data/lib/active_genie/{config → configs}/providers/google_config.rb +0 -0
  59. /data/lib/active_genie/{config → configs}/providers/openai_config.rb +0 -0
  60. /data/lib/active_genie/{config → configs}/providers/provider_base.rb +0 -0
  61. /data/lib/active_genie/{config → configs}/providers_config.rb +0 -0
  62. /data/lib/active_genie/{data_extractor/generalist.json → extractor/explanation.json} +0 -0
  63. /data/lib/active_genie/{data_extractor/generalist.prompt.md → extractor/explanation.prompt.md} +0 -0
  64. /data/lib/active_genie/{data_extractor/from_informal.json → extractor/litote.json} +0 -0
  65. /data/lib/active_genie/{factory → lister}/feud.json +0 -0
  66. /data/lib/active_genie/{factory → lister}/feud.prompt.md +0 -0
  67. /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 'players_collection'
3
+ require_relative 'entities/players'
4
4
  require_relative 'free_for_all'
5
- require_relative 'elo_round'
6
- require_relative 'ranking_scoring'
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
- # Ranking.call(players, criteria)
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 Ranking
33
- class Ranking
32
+ module Ranker
33
+ class Tournament
34
34
  def self.call(...)
35
35
  new(...).call
36
36
  end
37
37
 
38
- def initialize(param_players, criteria, reviewers: [], config: {})
39
- @param_players = param_players
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
- @players = create_players
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
- RankingScoring.call(
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.ranking.score_variation_threshold
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
- EloRound.call(
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({ ranking_id:, code: :ranking_final, players: players.map(&:to_h) })
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 ranking_id
129
- @ranking_id ||= begin
120
+ def ranker_id
121
+ @ranker_id ||= begin
130
122
  player_ids = @players.map(&:id).join(',')
131
- ranking_unique_key = [player_ids, @criteria, @config.to_json].join('-')
123
+ ranker_unique_key = [player_ids, @criteria, @config.to_json].join('-')
132
124
 
133
- Digest::MD5.hexdigest(ranking_unique_key)
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/config/providers/openai_config'
7
- require_relative 'active_genie/config/providers/google_config'
8
- require_relative 'active_genie/config/providers/anthropic_config'
9
- require_relative 'active_genie/config/providers/deepseek_config'
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 :DataExtractor, File.join(__dir__, 'active_genie/data_extractor')
13
- autoload :Battle, File.join(__dir__, 'active_genie/battle')
14
- autoload :Scoring, File.join(__dir__, 'active_genie/scoring')
15
- autoload :Ranking, File.join(__dir__, 'active_genie/ranking')
16
- autoload :Factory, File.join(__dir__, 'active_genie/factory')
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
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+ Rake::TestTask.new(:unit) do |t|
7
+ t.pattern = 'test/unit/**/*_test.rb'
8
+ end
9
+
10
+ Rake::TestTask.new(:integration) do |t|
11
+ t.pattern = 'test/integration/**/*_test.rb' # Or use _spec.rb for RSpec
12
+ end
13
+
14
+ task default: %i[unit integration]
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.29.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-07-16 00:00:00.000000000 Z
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,61 +23,62 @@ files:
23
23
  - README.md
24
24
  - VERSION
25
25
  - lib/active_genie.rb
26
- - lib/active_genie/battle.rb
27
- - lib/active_genie/battle/fight.json
28
- - lib/active_genie/battle/fight.prompt.md
29
- - lib/active_genie/battle/fight.rb
30
- - lib/active_genie/battle/generalist.json
31
- - lib/active_genie/battle/generalist.prompt.md
32
- - lib/active_genie/battle/generalist.rb
33
- - lib/active_genie/clients/providers/anthropic_client.rb
34
- - lib/active_genie/clients/providers/base_client.rb
35
- - lib/active_genie/clients/providers/deepseek_client.rb
36
- - lib/active_genie/clients/providers/google_client.rb
37
- - lib/active_genie/clients/providers/openai_client.rb
38
- - lib/active_genie/clients/unified_client.rb
39
- - lib/active_genie/config/battle_config.rb
40
- - lib/active_genie/config/data_extractor_config.rb
41
- - lib/active_genie/config/factory_config.rb
42
- - lib/active_genie/config/llm_config.rb
43
- - lib/active_genie/config/log_config.rb
44
- - lib/active_genie/config/providers/anthropic_config.rb
45
- - lib/active_genie/config/providers/deepseek_config.rb
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/factory.rb
62
- - lib/active_genie/factory/feud.json
63
- - lib/active_genie/factory/feud.prompt.md
64
- - lib/active_genie/factory/feud.rb
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/ranking.rb
67
- - lib/active_genie/ranking/elo_round.rb
68
- - lib/active_genie/ranking/free_for_all.rb
69
- - lib/active_genie/ranking/player.rb
70
- - lib/active_genie/ranking/players_collection.rb
71
- - lib/active_genie/ranking/ranking.rb
72
- - lib/active_genie/ranking/ranking_scoring.rb
73
- - lib/active_genie/scoring.rb
74
- - lib/active_genie/scoring/generalist.json
75
- - lib/active_genie/scoring/generalist.prompt.md
76
- - lib/active_genie/scoring/generalist.rb
77
- - lib/active_genie/scoring/recommended_reviewers.rb
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
81
+ - lib/tasks/test.rake
81
82
  homepage: https://github.com/Roriz/active_genie
82
83
  licenses:
83
84
  - Apache-2.0
@@ -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