active_genie 0.0.20 → 0.0.21

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d46586e4c64fdba00b703d32d2ee5eaad16e53e38f01adadb1a6090f049118d1
4
- data.tar.gz: f8420784cfd4b4ce21b2217af31d3e46252d623a65f0e93194027d9fd416b8ca
3
+ metadata.gz: a9c9c17c2c02f617c53edd6177ff72e0e2da34a4faf6bbeb9f9698b3858e4b69
4
+ data.tar.gz: 777620b958c17c9a439fcf5b8bdb3195564005e5becd8c41955c1c255c1a6ad3
5
5
  SHA512:
6
- metadata.gz: 7ab8e0d11276d5805d9ea3568c4f0c2a15d23fed01d8d762b8750cb6a2bd2f6a698a929b13b6bdf8da30d4b2b81187ab61160be9250b7e709b827389f925a9e2
7
- data.tar.gz: a6cddf62c9f6f19fe6fbe6982e8c6a2097b644280d0d86fea19e85da507e91b8dab3299304f182246f84c1cfa7c0e2e003c19781d827b66f15a5c34d10e36da5
6
+ metadata.gz: c3bee8941701e3516f48106d96165d78ea279cea1c7e5623515aed3361b5a337e191c85a3e4774a9526e3412a4b11f4c4f5d766e7f5a0e827cc74d869bd1ca54
7
+ data.tar.gz: a489c2f042aee21501697dfac47d0a37bd1a8bf50d990472dda2f7f8567615c3efd4422500653ac798c425a65df7bc065afaa3337f08a16305d4ef8f0b254a05
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Gem Version](https://badge.fury.io/rb/active_genie.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/active_genie)
5
5
  [![Ruby](https://github.com/roriz/active_genie/actions/workflows/benchmark.yml/badge.svg)](https://github.com/roriz/active_genie/actions/workflows/benchmark.yml)
6
6
 
7
- ActiveGenie is a Ruby gem that provides valuable solutions powered by Generative AI (GenAI) models. Just like Lodash or ActiveStorage, ActiveGenie brings a set of Modules reach real value fast and reliable.
7
+ ActiveGenie is a Ruby gem that provides valuable solutions powered by Generative AI (GenAI) models. Just like Lodash or ActiveStorage, ActiveGenie brings a set of Modules to reach real value fast and reliably.
8
8
  ActiveGenie is backed by a custom benchmarking system that ensures consistent quality and performance across different models and providers in every release.
9
9
 
10
10
  ## Installation
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.20
1
+ 0.0.21
@@ -122,7 +122,8 @@ module ActiveGenie::Battle
122
122
  description: 'Who is the winner based on the impartial judge reasoning?',
123
123
  enum: ['player_1', 'player_2']
124
124
  },
125
- }
125
+ },
126
+ required: %w[player_1_sell_himself player_2_sell_himself player_1_arguments player_2_counter impartial_judge_winner_reasoning impartial_judge_winner]
126
127
  }
127
128
  }
128
129
  end
@@ -33,21 +33,21 @@ module ActiveGenie
33
33
  # Defaults to 'gpt-4o-mini'.
34
34
  # @return [String] The lower tier model name.
35
35
  def lower_tier_model
36
- @lower_tier_model || 'gpt-4o-mini'
36
+ @lower_tier_model || 'gpt-4.1-mini'
37
37
  end
38
38
 
39
39
  # Retrieves the model name designated for the middle tier (e.g., balanced performance).
40
40
  # Defaults to 'gpt-4o'.
41
41
  # @return [String] The middle tier model name.
42
42
  def middle_tier_model
43
- @middle_tier_model || 'gpt-4o'
43
+ @middle_tier_model || 'gpt-4.1'
44
44
  end
45
45
 
46
46
  # Retrieves the model name designated for the upper tier (e.g., most capable).
47
47
  # Defaults to 'o1-preview'.
48
48
  # @return [String] The upper tier model name.
49
49
  def upper_tier_model
50
- @upper_tier_model || 'o1-preview'
50
+ @upper_tier_model || 'o3-mini'
51
51
  end
52
52
  end
53
53
  end
@@ -40,4 +40,34 @@ The method processes the players through scoring, elimination, and ranking phase
40
40
  - Adjust initial criteria to ensure consistency
41
41
  - Adjust each player's content to ensure consistency
42
42
  - Support players with images or audio
43
- - Parallelize processing battles and scoring
43
+ - Parallelize processing battles and scoring
44
+
45
+ ## Ranking Configuration
46
+
47
+ | Config | Description | Default |
48
+ |--------|-------------|---------|
49
+ | `score_variation_threshold` | Threshold for eliminating players with inconsistent scores | `30` |
50
+
51
+ ## Ranking Callbacks
52
+ Callbacks are optional and can be used to watch any changes in players, battles, or scoring.
53
+
54
+ | Callback | Description |
55
+ |--------|-------------|
56
+ | `watch_players` | Callback to watch any changes in players |
57
+ | `watch_battles` | Callback to watch any changes in battles |
58
+ | `watch_scoring` | Callback to watch any changes in scoring |
59
+
60
+ Example of callback usage:
61
+
62
+ ```ruby
63
+ result = ActiveGenie::Ranking.call(
64
+ players,
65
+ criteria,
66
+ config: {
67
+ watch_players: ->(player) { puts player },
68
+ watch_battles: ->(battle) { puts battle },
69
+ watch_scoring: ->(scoring) { puts scoring }
70
+ }
71
+ )
72
+ ```
73
+
@@ -76,6 +76,9 @@ module ActiveGenie::Ranking
76
76
  when 'draw' then [nil, nil]
77
77
  end
78
78
 
79
+ @config[:runtime][:watch_battle].call({ id: "#{player_1.id}_#{player_2.id}_#{elo_round_id}", player_1:, player_2:, winner:, loser:, reasoning: result['reasoning'] }) if @config[:runtime][:watch_battle]
80
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
81
+
79
82
  [winner, loser]
80
83
  end
81
84
  end
@@ -26,6 +26,8 @@ module ActiveGenie::Ranking
26
26
  winner.win!
27
27
  loser.lose!
28
28
  end
29
+
30
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
29
31
  end
30
32
  end
31
33
 
@@ -56,6 +58,7 @@ module ActiveGenie::Ranking
56
58
  when 'draw' then [nil, nil, result['reasoning']]
57
59
  end
58
60
 
61
+ @config[:runtime][:watch_battle].call({ id: "#{player_1.id}_#{player_2.id}_#{free_for_all_id}", player_1:, player_2:, winner:, loser:, reasoning: result['reasoning'] }) if @config[:runtime][:watch_battle]
59
62
  ActiveGenie::Logger.debug({
60
63
  code: :free_for_all_battle,
61
64
  player_ids: [player_1.id, player_2.id],
@@ -6,6 +6,7 @@ module ActiveGenie::Ranking
6
6
  params = { content: params } if params.is_a?(String)
7
7
 
8
8
  @content = params.dig(:content) || params
9
+ @name = params.dig(:name) || params.dig(:content)[0..10]
9
10
  @id = params.dig(:id) || Digest::MD5.hexdigest(@content)
10
11
  @score = params.dig(:score) || nil
11
12
  @elo = params.dig(:elo) || nil
@@ -15,9 +16,8 @@ module ActiveGenie::Ranking
15
16
  @eliminated = params.dig(:eliminated) || nil
16
17
  end
17
18
 
18
- attr_reader :id, :content, :score, :elo,
19
- :ffa_win_count, :ffa_lose_count, :ffa_draw_count,
20
- :eliminated
19
+ attr_reader :id, :content, :score, :elo, :ffa_win_count,
20
+ :ffa_lose_count, :ffa_draw_count, :eliminated
21
21
  attr_accessor :rank
22
22
 
23
23
  def score=(value)
@@ -51,15 +51,27 @@ module ActiveGenie::Ranking
51
51
  ActiveGenie::Logger.debug({ code: :new_ffa_score, player_id: id, result: 'lose', ffa_score: })
52
52
  end
53
53
 
54
+ def name
55
+ @name
56
+ end
57
+
54
58
  def ffa_score
55
59
  @ffa_win_count * 3 + @ffa_draw_count
56
60
  end
57
61
 
62
+ def sort_value
63
+ (ffa_score * 1000000) + ((elo || 0) * 100) + (score || 0)
64
+ end
65
+
66
+ def to_json
67
+ to_h.to_json
68
+ end
69
+
58
70
  def to_h
59
71
  {
60
- id:, content:, score:, elo:,
72
+ id:, name:, content:, score:, elo:,
61
73
  ffa_win_count:, ffa_lose_count:, ffa_draw_count:,
62
- eliminated:, ffa_score:
74
+ eliminated:, ffa_score:, sort_value:
63
75
  }
64
76
  end
65
77
 
@@ -41,10 +41,14 @@ module ActiveGenie::Ranking
41
41
  end
42
42
 
43
43
  def sorted
44
- sorted_players = @players.sort_by { |p| [-p.ffa_score, -(p.elo || 0), -(p.score || 0)] }
44
+ sorted_players = @players.sort_by { |p| -p.sort_value }
45
45
  sorted_players.each_with_index { |p, i| p.rank = i + 1 }
46
46
  sorted_players
47
47
  end
48
+
49
+ def to_json
50
+ to_h.to_json
51
+ end
48
52
 
49
53
  def to_h
50
54
  sorted.map { |p| p.to_h }
@@ -67,7 +67,7 @@ module ActiveGenie::Ranking
67
67
 
68
68
  private
69
69
 
70
- SCORE_VARIATION_THRESHOLD = 15
70
+ DEFAULT_SCORE_VARIATION_THRESHOLD = 30
71
71
  ELIMINATION_VARIATION = 'variation_too_high'
72
72
  ELIMINATION_RELEGATION = 'relegation_tier'
73
73
 
@@ -80,27 +80,36 @@ module ActiveGenie::Ranking
80
80
  end
81
81
 
82
82
  def set_initial_player_scores!
83
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
83
84
  RankingScoring.call(@players, @criteria, reviewers: @reviewers, config: @config)
85
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
84
86
  end
85
87
 
86
88
  def eliminate_obvious_bad_players!
87
- while @players.coefficient_of_variation >= SCORE_VARIATION_THRESHOLD
89
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
90
+ while @players.coefficient_of_variation >= score_variation_threshold
88
91
  @players.eligible.last.eliminated = ELIMINATION_VARIATION
89
92
  end
93
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
90
94
  end
91
95
 
92
96
  def run_elo_round!
97
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
93
98
  @elo_rounds_played += 1
94
99
 
95
100
  elo_report = EloRound.call(@players, @criteria, config: @config)
96
101
 
97
102
  @elo_round_battle_count += elo_report[:battles_count]
98
103
 
104
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
99
105
  elo_report
100
106
  end
101
107
 
102
108
  def eliminate_relegation_players!
109
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
103
110
  @players.calc_relegation_tier.each { |player| player.eliminated = ELIMINATION_RELEGATION }
111
+
112
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
104
113
  end
105
114
 
106
115
  def rebalance_players!(elo_report)
@@ -111,12 +120,19 @@ module ActiveGenie::Ranking
111
120
 
112
121
  player.elo += elo_report[:highest_elo_diff]
113
122
  end
123
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
114
124
  end
115
125
 
116
126
  def run_free_for_all!
127
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
117
128
  ffa_report = FreeForAll.call(@players, @criteria, config: @config)
118
129
 
119
130
  @free_for_all_battle_count += ffa_report[:battles_count]
131
+ @config[:runtime][:watch_players].call(@players) if @config[:runtime][:watch_players]
132
+ end
133
+
134
+ def score_variation_threshold
135
+ @config[:runtime][:score_variation_threshold] || DEFAULT_SCORE_VARIATION_THRESHOLD
120
136
  end
121
137
 
122
138
  def report
@@ -16,10 +16,27 @@ module ActiveGenie::Ranking
16
16
  def call
17
17
  ActiveGenie::Logger.with_context(log_context) do
18
18
  @reviewers = generate_reviewers
19
+
20
+ players_to_score = players_without_score
21
+ until players_to_score.empty?
22
+ threads = []
23
+ mutex = Mutex.new
24
+
25
+ # Take up to 3 players for parallel processing
26
+ current_batch = players_to_score.shift(3)
19
27
 
20
- players_without_score.each do |player|
21
- # TODO: This can take a while, can be parallelized
22
- player.score = generate_score(player)
28
+ current_batch.each do |player|
29
+ threads << Thread.new(player) do |p|
30
+ score = generate_score(p)
31
+
32
+ mutex.synchronize do
33
+ p.score = score
34
+ end
35
+ end
36
+ end
37
+
38
+ # Wait for all threads in this batch to complete
39
+ threads.each(&:join)
23
40
  end
24
41
  end
25
42
  end
@@ -39,6 +56,11 @@ module ActiveGenie::Ranking
39
56
  ).values_at('final_score', 'final_reasoning')
40
57
 
41
58
  ActiveGenie::Logger.debug({ code: :new_score, player_id: player.id, score:, reasoning: })
59
+ @config[:runtime][:watch_scoring].call({
60
+ player_id: player.id,
61
+ player_name: player.content[0..10],
62
+ score: player.score
63
+ }) if @config[:runtime][:watch_scoring]
42
64
 
43
65
  score
44
66
  end
@@ -65,7 +87,7 @@ module ActiveGenie::Ranking
65
87
  player_ids = players_without_score.map(&:id).join(',')
66
88
  ranking_unique_key = [player_ids, @criteria, @config.to_json].join('-')
67
89
 
68
- Digest::MD5.hexdigest(ranking_unique_key)
90
+ Digest::MD5.hexdigest(ranking_unique_key) + '-scoring'
69
91
  end
70
92
  end
71
93
  end
metadata CHANGED
@@ -1,121 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_genie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Radamés Roriz
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-04-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: "# ActiveGenie \U0001F9DE‍♂️\n> The lodash for GenAI, stop reinventing
14
- the wheel\n\n[![Gem Version](https://badge.fury.io/rb/active_genie.svg?icon=si%3Arubygems)](https://badge.fury.io/rb/active_genie)\n[![Ruby](https://github.com/roriz/active_genie/actions/workflows/benchmark.yml/badge.svg)](https://github.com/roriz/active_genie/actions/workflows/benchmark.yml)\n\nActiveGenie
15
- is a Ruby gem that provides valuable solutions powered by Generative AI (GenAI)
16
- models. Just like Lodash or ActiveStorage, ActiveGenie brings a set of Modules reach
17
- real value fast and reliable.\nActiveGenie is backed by a custom benchmarking system
18
- that ensures consistent quality and performance across different models and providers
19
- in every release.\n\n## Installation\n\n1. Add to your Gemfile:\n```ruby\ngem 'active_genie'\n```\n\n2.
20
- Install the gem:\n```shell\nbundle install\n```\n\n3. Generate the configuration:\n```shell\necho
21
- \"ActiveGenie.load_tasks\" >> Rakefile\nrails g active_genie:install\n```\n\n4.
22
- Configure your credentials in `config/initializers/active_genie.rb`:\n```ruby\nActiveGenie.configure
23
- do |config|\n config.openai.api_key = ENV['OPENAI_API_KEY']\nend\n```\n\n## Quick
24
- Start\n\n### Data Extractor\n\nExtract structured data from text using AI-powered
25
- analysis, handling informal language and complex expressions.\n\n```ruby\ntext =
26
- \"Nike Air Max 90 - Size 42 - $199.99\"\nschema = {\n brand: { \n type: 'string',\n
27
- \ enum: [\"Nike\", \"Adidas\", \"Puma\"]\n },\n price: { \n type: 'number',\n
28
- \ minimum: 0\n },\n size: {\n type: 'number',\n minimum: 35,\n maximum:
29
- 46\n }\n}\n\nresult = ActiveGenie::DataExtractor.call(\n text,\n schema,\n config:
30
- { provider: :openai, model: 'gpt-4o-mini' } # optional\n)\n# => { \n# brand:
31
- \"Nike\", \n# brand_explanation: \"Brand name found at start of text\",\n#
32
- \ price: 199.99,\n# price_explanation: \"Price found in USD format at end\",\n#
33
- \ size: 42,\n# size_explanation: \"Size explicitly stated in the middle\"\n#
34
- \ }\n```\n\n*Recommended model*: `gpt-4o-mini`\n\nFeatures:\n- Structured data
35
- extraction with type validation\n- Schema-based extraction with custom constraints\n-
36
- Informal text analysis (litotes, hedging)\n- Detailed explanations for extracted
37
- values\n\nSee the [Data Extractor README](lib/active_genie/data_extractor/README.md)
38
- for informal text processing, advanced schemas, and detailed interface documentation.\n\n###
39
- Scoring\nText evaluation system that provides detailed scoring and feedback using
40
- multiple expert reviewers. Get balanced scoring through AI-powered expert reviewers
41
- that automatically adapt to your content.\n\n```ruby\ntext = \"The code implements
42
- a binary search algorithm with O(log n) complexity\"\ncriteria = \"Evaluate technical
43
- accuracy and clarity\"\n\nresult = ActiveGenie::Scoring.basic(\n text,\n criteria,\n
44
- \ config: { provider: :anthropic, model: 'claude-3-5-haiku-20241022' } # optional\n)\n#
45
- => {\n# algorithm_expert_score: 95,\n# algorithm_expert_reasoning: \"Accurately
46
- describes binary search and its complexity\",\n# technical_writer_score: 90,\n#
47
- \ technical_writer_reasoning: \"Clear and concise explanation of the algorithm\",\n#
48
- \ final_score: 92.5\n# }\n```\n\n*Recommended model*: `claude-3-5-haiku-20241022`\n\nFeatures:\n-
49
- Multi-reviewer evaluation with automatic expert selection\n- Detailed feedback with
50
- scoring reasoning\n- Customizable reviewer weights\n- Flexible evaluation criteria\n\nSee
51
- the [Scoring README](lib/active_genie/scoring/README.md) for advanced usage, custom
52
- reviewers, and detailed interface documentation.\n\n### Battle\nAI-powered battle
53
- evaluation system that determines winners between two players based on specified
54
- criteria.\n\n```ruby\nrequire 'active_genie'\n\nplayer_1 = \"Implementation uses
55
- dependency injection for better testability\"\nplayer_2 = \"Code has high test coverage
56
- but tightly coupled components\"\ncriteria = \"Evaluate code quality and maintainability\"\n\nresult
57
- = ActiveGenie::Battle.call(\n player_1,\n player_2,\n criteria,\n config: {
58
- provider: :google, model: 'gemini-2.0-flash-lite' } # optional\n)\n# => {\n# winner_player:
59
- \"Implementation uses dependency injection for better testability\",\n# reasoning:
60
- \"Player 1 implementation demonstrates better maintainability through dependency
61
- injection, \n# which allows for easier testing and component replacement.
62
- While Player 2 has good test coverage, \n# the tight coupling makes
63
- the code harder to maintain and modify.\",\n# what_could_be_changed_to_avoid_draw:
64
- \"Focus on specific architectural patterns and design principles\"\n# }\n```\n\n*Recommended
65
- model*: `claude-3-5-haiku`\n\nFeatures:\n- Multi-reviewer evaluation with automatic
66
- expert selection\n- Detailed feedback with scoring reasoning\n- Customizable reviewer
67
- weights\n- Flexible evaluation criteria\n\nSee the [Battle README](lib/active_genie/battle/README.md)
68
- for advanced usage, custom reviewers, and detailed interface documentation.\n\n###
69
- Ranking\nThe Ranking module provides competitive ranking through multi-stage evaluation:\n\n```ruby\nrequire
70
- 'active_genie'\n\nplayers = ['REST API', 'GraphQL API', 'SOAP API', 'gRPC API',
71
- 'Websocket API']\ncriteria = \"Best one to be used into a high changing environment\"\n\nresult
72
- = ActiveGenie::Ranking.call(\n players,\n criteria,\n config: { provider: :google,
73
- model: 'gemini-2.0-flash-lite' } # optional\n)\n# => {\n# winner_player: \"gRPC
74
- API\",\n# reasoning: \"gRPC API is the best one to be used into a high changing
75
- environment\",\n# }\n```\n\n*Recommended model*: `gemini-2.0-flash-lite`\n\n-
76
- **Multi-phase ranking system** combining expert scoring and ELO algorithms\n- **Automatic
77
- elimination** of inconsistent performers using statistical analysis\n- **Dynamic
78
- ranking adjustments** based on simulated pairwise battles, from bottom to top\n\nSee
79
- the [Ranking README](lib/active_genie/ranking/README.md) for implementation details,
80
- configuration, and advanced ranking strategies.\n\n### Text Summarizer (Future)\n###
81
- Categorizer (Future)\n### Language detector (Future)\n### Translator (Future)\n###
82
- Sentiment analyzer (Future)\n\n## Benchmarking \U0001F9EA\n\nActiveGenie includes
83
- a comprehensive benchmarking system to ensure consistent, high-quality outputs across
84
- different LLM models and providers.\n\n```ruby\n# Run all benchmarks\nbundle exec
85
- rake active_genie:benchmark\n\n# Run benchmarks for a specific module\nbundle exec
86
- rake active_genie:benchmark[data_extractor]\n```\n\n### Latest Results\n\n| Model
87
- | Overall Precision |\n|-------|-------------------|\n| claude-3-5-haiku-20241022
88
- | 92.25% |\n| gemini-2.0-flash-lite | 84.25% |\n| gpt-4o-mini | 62.75% |\n| deepseek-chat
89
- | 57.25% |\n\nSee the [Benchmark README](benchmark/README.md) for detailed results,
90
- methodology, and how to contribute to our test suite.\n\n## Configuration\n\n| Config
91
- | Description | Default |\n|--------|-------------|---------|\n| `provider` | LLM
92
- provider (openai, anthropic, etc) | `nil` |\n| `model` | Model to use | `nil` |\n|
93
- `api_key` | Provider API key | `nil` |\n| `timeout` | Request timeout in seconds
94
- | `5` |\n| `max_retries` | Maximum retry attempts | `3` |\n\n> **Note:** Each module
95
- can append its own set of configuration, see the individual module documentation
96
- for details.\n\n## How to create a new provider\n\nActiveGenie supports adding custom
97
- providers to integrate with different LLM services. To create a new provider:\n\n1.
98
- Create a configuration class for your provider in `lib/active_genie/configuration/providers/`:\n\n```ruby\n#
99
- Example: lib/active_genie/configuration/providers/internal_company_api_config.rb\nmodule
100
- ActiveGenie\n module Configuration::Providers\n class InternalCompanyApiConfig
101
- < BaseConfig\n NAME = :internal_company_api\n \n # API key accessor
102
- with environment variable fallback\n def api_key\n @api_key || ENV['INTERNAL_COMPANY_API_KEY']\n
103
- \ end\n \n # Base API URL\n def api_url\n @api_url ||
104
- 'https://api.internal-company.com/v1'\n end\n \n # Client instantiation\n
105
- \ def client\n @client ||= ::ActiveGenie::Clients::InternalCompanyApiClient.new(self)\n
106
- \ end\n \n # Model tier definitions\n def lower_tier_model\n
107
- \ @lower_tier_model || 'internal-basic'\n end\n \n def middle_tier_model\n
108
- \ @middle_tier_model || 'internal-standard'\n end\n \n def
109
- upper_tier_model\n @upper_tier_model || 'internal-premium'\n end\n end\n
110
- \ end\nend\n```\n\n2. Register your provider in your configuration:\n\n```ruby\n#
111
- In config/initializers/active_genie.rb\nActiveGenie.configure do |config|\n # Register
112
- your custom provider\n config.providers.register(InternalCompanyApi::Configuration)\n
113
- \ \n # Configure your provider\n config.internal_company_api.api_key = ENV['INTERNAL_COMPANY_API_KEY']\nend\n```\n\n##
114
- Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout
115
- -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing
116
- feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5.
117
- Open a Pull Request\n\n## License\n\nThis project is licensed under the Apache License
118
- 2.0 License - see the [LICENSE](LICENSE) file for details.\n"
13
+ the wheel\n\nActiveGenie is a Ruby gem that provides valuable solutions powered
14
+ by Generative AI (GenAI) models. Just like Lodash or ActiveStorage, ActiveGenie
15
+ brings a set of Modules to reach real value fast and reliably.\nActiveGenie is backed
16
+ by a custom benchmarking system that ensures consistent quality and performance
17
+ across different models and providers in every release.\n\n## Features\n\n* **Data
18
+ Extractor:** Extract structured data from text using AI-powered analysis\n* **Scoring:**
19
+ Text evaluation system with detailed scoring and feedback\n* **Battle:** AI-powered
20
+ battle evaluation system between two players\n* **Ranking:** Multi-phase ranking
21
+ system for multiple options\n\n### Performance Breakdown\n\n| ActiveGenie Module
22
+ | Best Precision | Worst Precision | Recommended Model |\n|--------------------|-------------------|-------------------|-------------------|\n|
23
+ data_extractor | 100% | 86% | `gpt-4o-mini` |\n| battle | 100% | 10% | `gemini-2.0-flash-lite`
24
+ |\n| scoring | 69% | 61% | `claude-3-5-haiku-20241022` |\n| ranking | 100% | 0%
25
+ | `gemini-2.0-flash-lite` |\n\nSee the [GitHub repository](https://github.com/Roriz/active_genie)
26
+ for complete documentation and examples.\n"
119
27
  email:
120
28
  - radames@roriz.dev
121
29
  executables: []
@@ -175,7 +83,6 @@ metadata:
175
83
  changelog_uri: https://github.com/Roriz/active_genie/blob/master/CHANGELOG.md
176
84
  bug_tracker_uri: https://github.com/Roriz/active_genie/issues
177
85
  rubygems_mfa_required: 'true'
178
- post_install_message:
179
86
  rdoc_options: []
180
87
  require_paths:
181
88
  - lib
@@ -190,8 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
97
  - !ruby/object:Gem::Version
191
98
  version: '0'
192
99
  requirements: []
193
- rubygems_version: 3.5.3
194
- signing_key:
100
+ rubygems_version: 3.6.7
195
101
  specification_version: 4
196
102
  summary: Transform your Ruby application with powerful, production-ready GenAI features
197
103
  test_files: []