active_genie 0.0.10 → 0.0.12
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 +17 -54
- data/VERSION +1 -1
- data/lib/active_genie/battle/basic.rb +49 -58
- data/lib/active_genie/clients/openai_client.rb +60 -18
- data/lib/active_genie/clients/unified_client.rb +2 -2
- data/lib/active_genie/configuration/openai_config.rb +9 -9
- data/lib/active_genie/data_extractor/README.md +0 -1
- data/lib/active_genie/data_extractor/basic.rb +8 -18
- data/lib/active_genie/data_extractor/from_informal.rb +4 -15
- data/lib/active_genie/logger.rb +34 -7
- data/lib/active_genie/{league → ranking}/README.md +7 -7
- data/lib/active_genie/ranking/elo_round.rb +113 -0
- data/lib/active_genie/ranking/free_for_all.rb +76 -0
- data/lib/active_genie/ranking/player.rb +97 -0
- data/lib/active_genie/{league → ranking}/players_collection.rb +18 -11
- data/lib/active_genie/ranking/ranking.rb +98 -0
- data/lib/active_genie/ranking/ranking_scoring.rb +71 -0
- data/lib/active_genie/ranking.rb +12 -0
- data/lib/active_genie/scoring/README.md +1 -1
- data/lib/active_genie/scoring/basic.rb +55 -30
- data/lib/active_genie/scoring/{recommended_reviews.rb → recommended_reviewers.rb} +18 -7
- data/lib/active_genie/scoring.rb +3 -3
- data/lib/active_genie.rb +1 -1
- metadata +66 -87
- data/lib/active_genie/league/elo_ranking.rb +0 -121
- data/lib/active_genie/league/free_for_all.rb +0 -62
- data/lib/active_genie/league/league.rb +0 -120
- data/lib/active_genie/league/player.rb +0 -59
- data/lib/active_genie/league.rb +0 -12
| @@ -1,120 +0,0 @@ | |
| 1 | 
            -
            require 'securerandom'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require_relative './players_collection'
         | 
| 4 | 
            -
            require_relative './free_for_all'
         | 
| 5 | 
            -
            require_relative './elo_ranking'
         | 
| 6 | 
            -
            require_relative '../scoring/recommended_reviews'
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            # This class orchestrates player ranking through multiple evaluation stages
         | 
| 9 | 
            -
            # using Elo ranking and free-for-all match simulations.
         | 
| 10 | 
            -
            # 1. Sets initial scores
         | 
| 11 | 
            -
            # 2. Eliminates low performers
         | 
| 12 | 
            -
            # 3. Runs Elo ranking (for large groups)
         | 
| 13 | 
            -
            # 4. Conducts free-for-all matches
         | 
| 14 | 
            -
            #
         | 
| 15 | 
            -
            # @example Basic usage
         | 
| 16 | 
            -
            #   League.call(players, criteria)
         | 
| 17 | 
            -
            #
         | 
| 18 | 
            -
            # @param param_players [Array] Collection of player objects to evaluate
         | 
| 19 | 
            -
            #   Example: ["Circle", "Triangle", "Square"]
         | 
| 20 | 
            -
            #            or
         | 
| 21 | 
            -
            #   [
         | 
| 22 | 
            -
            #     { content: "Circle", score: 10 },
         | 
| 23 | 
            -
            #     { content: "Triangle", score: 7 },
         | 
| 24 | 
            -
            #     { content: "Square", score: 5 }
         | 
| 25 | 
            -
            #   ]
         | 
| 26 | 
            -
            # @param criteria [String] Evaluation criteria configuration
         | 
| 27 | 
            -
            #   Example: "What is more similar to the letter 'O'?"
         | 
| 28 | 
            -
            # @param config [Hash] Additional configuration config
         | 
| 29 | 
            -
            #   Example: { model: "gpt-4o", api_key: ENV['OPENAI_API_KEY'] }
         | 
| 30 | 
            -
            # @return [Hash] Final ranked player results
         | 
| 31 | 
            -
            module ActiveGenie::League
         | 
| 32 | 
            -
              class League
         | 
| 33 | 
            -
                def self.call(param_players, criteria, config: {})
         | 
| 34 | 
            -
                  new(param_players, criteria, config:).call
         | 
| 35 | 
            -
                end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                def initialize(param_players, criteria, config: {})
         | 
| 38 | 
            -
                  @param_players = param_players
         | 
| 39 | 
            -
                  @criteria = criteria
         | 
| 40 | 
            -
                  @config = config
         | 
| 41 | 
            -
                  @league_id = SecureRandom.uuid
         | 
| 42 | 
            -
                  @start_time = Time.now
         | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                def call
         | 
| 46 | 
            -
                  set_initial_score_players
         | 
| 47 | 
            -
                  eliminate_obvious_bad_players
         | 
| 48 | 
            -
                  run_elo_ranking if players.eligible_size > 10
         | 
| 49 | 
            -
                  run_free_for_all
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                  ActiveGenie::Logger.info({ **log, step: :league_end, top5: players.first(5).map(&:id) })
         | 
| 52 | 
            -
                  players.to_h
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                private
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                SCORE_VARIATION_THRESHOLD = 10
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                def set_initial_score_players
         | 
| 60 | 
            -
                  players_without_score = players.reject { |player| player.score }
         | 
| 61 | 
            -
                  players_without_score.each do |player|
         | 
| 62 | 
            -
                    player.score = generate_score(player.content) # This can take a while, can be parallelized
         | 
| 63 | 
            -
                    ActiveGenie::Logger.trace({ **log, step: :player_score, player_id: player.id, score: player.score })
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                  ActiveGenie::Logger.info({ **log, step: :initial_score, evaluated_players: players_without_score.size })
         | 
| 67 | 
            -
                end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                def generate_score(content)
         | 
| 70 | 
            -
                  ActiveGenie::Scoring::Basic.call(content, @criteria, reviewers, config:)['final_score']
         | 
| 71 | 
            -
                end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                def eliminate_obvious_bad_players
         | 
| 74 | 
            -
                  eliminated_count = 0
         | 
| 75 | 
            -
                  while players.coefficient_of_variation >= SCORE_VARIATION_THRESHOLD
         | 
| 76 | 
            -
                    players.eligible.last.eliminated = 'variation_too_high'
         | 
| 77 | 
            -
                    eliminated_count += 1
         | 
| 78 | 
            -
                  end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                  ActiveGenie::Logger.info({ **log, step: :eliminate_obvious_bad_players, eliminated_count: })
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                def run_elo_ranking
         | 
| 84 | 
            -
                  EloRanking.call(players, @criteria, config:)
         | 
| 85 | 
            -
                end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                def run_free_for_all
         | 
| 88 | 
            -
                  FreeForAll.call(players, @criteria, config:)
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                def reviewers
         | 
| 92 | 
            -
                  [recommended_reviews['reviewer1'], recommended_reviews['reviewer2'], recommended_reviews['reviewer3']]
         | 
| 93 | 
            -
                end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                def recommended_reviews
         | 
| 96 | 
            -
                  @recommended_reviews ||= ActiveGenie::Scoring::RecommendedReviews.call(
         | 
| 97 | 
            -
                    [players.sample.content, players.sample.content].join("\n\n"),
         | 
| 98 | 
            -
                    @criteria,
         | 
| 99 | 
            -
                    config:
         | 
| 100 | 
            -
                  )
         | 
| 101 | 
            -
                end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                def players
         | 
| 104 | 
            -
                  @players ||= PlayersCollection.new(@param_players)
         | 
| 105 | 
            -
                end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                def config
         | 
| 108 | 
            -
                  { log:, **@config }
         | 
| 109 | 
            -
                end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                def log
         | 
| 112 | 
            -
                  {
         | 
| 113 | 
            -
                    **(@config.dig(:log) || {}),
         | 
| 114 | 
            -
                    league_id: @league_id,
         | 
| 115 | 
            -
                    league_start_time: @start_time,
         | 
| 116 | 
            -
                    duration: Time.now - @start_time
         | 
| 117 | 
            -
                  }
         | 
| 118 | 
            -
                end
         | 
| 119 | 
            -
              end
         | 
| 120 | 
            -
            end
         | 
| @@ -1,59 +0,0 @@ | |
| 1 | 
            -
            require 'securerandom'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module ActiveGenie::Leaderboard
         | 
| 4 | 
            -
              class Player
         | 
| 5 | 
            -
                def initialize(params)
         | 
| 6 | 
            -
                  params = { content: params } if params.is_a?(String)
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  @id = params.dig(:id) || SecureRandom.uuid
         | 
| 9 | 
            -
                  @content = params.dig(:content) || params
         | 
| 10 | 
            -
                  @score = params.dig(:score) || nil
         | 
| 11 | 
            -
                  @elo = params.dig(:elo) || nil
         | 
| 12 | 
            -
                  @free_for_all = {
         | 
| 13 | 
            -
                    win: params.dig(:free_for_all, :win) || 0,
         | 
| 14 | 
            -
                    lose: params.dig(:free_for_all, :lose) || 0,
         | 
| 15 | 
            -
                    draw: params.dig(:free_for_all, :draw) || 0
         | 
| 16 | 
            -
                  }
         | 
| 17 | 
            -
                  @eliminated = params.dig(:eliminated) || nil
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                attr_reader :id, :content, :score, :elo, :free_for_all, :eliminated
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                def generate_elo_by_score
         | 
| 23 | 
            -
                  return if !@elo.nil?
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  if @score.nil?
         | 
| 26 | 
            -
                    @elo = BASE_ELO
         | 
| 27 | 
            -
                  else
         | 
| 28 | 
            -
                    @elo = BASE_ELO + (@score - 50)
         | 
| 29 | 
            -
                  end
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                def score=(value)
         | 
| 33 | 
            -
                  @score = value
         | 
| 34 | 
            -
                end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                def elo=(value)
         | 
| 37 | 
            -
                  @elo = value
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                def eliminated=(value)
         | 
| 41 | 
            -
                  @eliminated = value
         | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                def free_for_all_score
         | 
| 45 | 
            -
                  @free_for_all[:win] * 3 + @free_for_all[:draw]
         | 
| 46 | 
            -
                end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                def to_h
         | 
| 49 | 
            -
                  {
         | 
| 50 | 
            -
                    id:, content:, score:, elo:,
         | 
| 51 | 
            -
                    eliminated:, free_for_all:, free_for_all_score:
         | 
| 52 | 
            -
                  }
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                private
         | 
| 56 | 
            -
                
         | 
| 57 | 
            -
                BASE_ELO = 1000
         | 
| 58 | 
            -
              end
         | 
| 59 | 
            -
            end
         | 
    
        data/lib/active_genie/league.rb
    DELETED