agent-evals 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56fb5b0637a74afe1bf8be4010c7ee38f9e0838d2dc0e449e01dae294fb2fdd9
4
- data.tar.gz: 7d9dd13e1d1df76b9ce6b38813775285921505b12ba863c37b730d223ef552d1
3
+ metadata.gz: fce409377a09747fbca5b2cfce6beee74761377b73395773aa65a59409c05fcc
4
+ data.tar.gz: 6120e86241b88d81b0b057fd6bc6b5c429654dde2978b22c21a23f0c1b5ab25b
5
5
  SHA512:
6
- metadata.gz: 82e38be379ec294b9f6d866ca3d2e7e83651a6790a6021a1010b430a53571389531b63c65faa1e58ba937de466f59c2a50187f04481ad2eaf3406efe5b9bedac
7
- data.tar.gz: e955b8dfbdb2bb4194e7cf7712bc0cbba395b86d8534c24eb97493d66185dbbf8503c1bf62c648bd92e180274311b6a3b5d41fb57ffeb60ea6b3ab9273bb0c49
6
+ metadata.gz: e4c19f34da26df191552facd225fd003bfd0c7a59e172ecf87e1f6255ef274249f2ea6146d617f8426be1dd0c4d91d702624a3799f3573ce05613b631eb0b2b5
7
+ data.tar.gz: 7bfd5bf66da297c8d4b3e928cb67a046714a166f1df45a2da74b2e25b86f3bb3ef53309fb1511bf6149584355e2cd55e5591efddafcc0b1b06c15fea4da7e6b7
data/README.md CHANGED
@@ -389,9 +389,9 @@ agent-evals completion zsh # shell completion (bash too)
389
389
 
390
390
  - `cases` prints one row per case: dataset, id, difficulty, the scorer's `summary`, word count.
391
391
  - `verify` reports empty inputs and missing or unparsable `expected.json`, then runs `adapter.verify(dataset)` and `scorer.verify`.
392
- - `run` and `compare` run one experiment per model and dataset. `compare --concurrency N` limits how many models run at once.
392
+ - `run` and `compare` run one experiment per model and dataset, as many at once as the machine has CPUs. `-j N` / `--concurrency N` sets another limit, and `-j 0` starts them all together. `-p` is separate: the cases in flight inside each experiment.
393
393
 
394
- Flags shared by `run` and `compare`: `-m/--models`, `-d/--dataset` (every dataset when omitted), `-c/--case`, `-e/--effort`, `-t/--temperature`, `--max-tokens`, `-p/--parallelism`, `--config FILE`, `--project NAME`, `--tracker NAME`, `--local`, `--no-open`, `-n/--dry-run`, `-o/--output [FILE]`. `-l` and `-L` are reserved for logging and not yet implemented.
394
+ Flags shared by `run` and `compare`: `-m/--models`, `-d/--dataset` (every dataset when omitted), `-c/--case`, `-e/--effort`, `-t/--temperature`, `--max-tokens`, `-p/--parallelism`, `-j/--concurrency`, `-C/--config FILE`, `--project NAME`, `--tracker NAME`, `--local`, `--no-open`, `-n/--dry-run`, `-o/--output [FILE]`. `-l` and `-L` are reserved for logging and not yet implemented.
395
395
 
396
396
  **Reading the output.** The leaderboard has one column per metric the scorer declares, ranked by the `primary` one, with a glossary built from each metric's `description`. STDOUT carries the tables. Progress bars and warnings go to STDERR, and anything a library prints while the bars redraw is saved to `log/<command>.warnings.<stamp>.log` instead of garbling the screen.
397
397
 
@@ -8,16 +8,14 @@ module Agent
8
8
  class Compare < ModelCommand
9
9
  desc "Run every case against several models and print a leaderboard"
10
10
 
11
- option :concurrency, default: "0", desc: "Models running at once; 0 runs them all together"
12
-
13
11
  example [
14
12
  " # everything .agent-eval.config.yml lists",
15
13
  "-m anthropic/claude-haiku-5.5,openai/gpt-4o-mini -t 0",
16
- "-e low -c clear --concurrency 2",
14
+ "-e low -c clear -j 2 # two experiments at a time",
17
15
  "-n # show the matrix, spend nothing"
18
16
  ]
19
17
 
20
- def call(models:, dataset:, dry_run:, concurrency:, **options)
18
+ def call(models:, dataset:, dry_run:, **options)
21
19
  config = lineup(options)
22
20
  contenders = contenders(config, models, options)
23
21
  datasets = datasets(dataset)
@@ -25,7 +23,7 @@ module Agent
25
23
 
26
24
  setup!(contenders, options)
27
25
  runs = datasets.flat_map { |name| contenders.map { experiment(it, config, options, dataset: name) } }
28
- report(execute(runs, concurrency: Integer(concurrency)), output: options[:output], open: options[:open])
26
+ report(execute(runs, concurrency: concurrency(options)), output: options[:output], open: options[:open])
29
27
  end
30
28
  end
31
29
  end
@@ -47,7 +47,7 @@ module Agent
47
47
  aliases: ["-d"],
48
48
  default: [],
49
49
  desc: "Datasets, comma-separated; every dataset when omitted. Each model runs on each"
50
- subclass.option :config, desc: "The lineup file (default: the suite's .agent-eval..agent-eval.config.yml)"
50
+ subclass.option :config, aliases: ["-C"], desc: "The lineup file (default: the suite's .agent-eval.config.yml)"
51
51
  subclass.option :effort, aliases: ["-e"], desc: "Reasoning effort: default, or one the provider accepts (overrides the config file)"
52
52
  subclass.option :temperature, aliases: ["-t"], desc: "Sampling temperature, or 'default' to send none (overrides the config file)"
53
53
  subclass.option :max_tokens, desc: "Output token cap, reasoning included (overrides the config file)"
@@ -57,6 +57,9 @@ module Agent
57
57
  default: [],
58
58
  desc: "Only these cases, by id prefix: -c clear or -c clear/003,vague/001"
59
59
  subclass.option :parallelism, aliases: ["-p"], desc: "Cases in flight at once, per model (default: the config's defaults.parallelism)"
60
+ subclass.option :concurrency,
61
+ aliases: ["-j"],
62
+ desc: "Experiments running at once; 0 runs them all together (default: the number of CPUs)"
60
63
  subclass.option :project,
61
64
  desc: "Braintrust project name; default is the BRAINTRUST_PROJECT_ID project, else the config file's project"
62
65
  subclass.option :open,
@@ -179,13 +182,26 @@ module Agent
179
182
  # @param runs [Array<Experiment>]
180
183
  # @param concurrency [Integer] experiments at once; 0 runs them all together
181
184
  # @return [Array<Experiment::Summary>]
182
- def execute(runs, concurrency: 0)
185
+ def execute(runs, concurrency:)
183
186
  summaries = Array.new(runs.size)
184
187
  warnings.capture { bars(runs, summaries, concurrency) }
185
188
  summaries.compact.each { |s| s.errors.each { warnings.record("[#{s.name}] #{it}") } }
186
189
  summaries.compact
187
190
  end
188
191
 
192
+ # -j, else one experiment per CPU. Uncapped, a full lineup started
193
+ # every model x dataset pair at once: 140 experiments, each with its
194
+ # own pool of case threads, all fighting for the network and the screen.
195
+ #
196
+ # @return [Integer] experiments at once; 0 means all of them
197
+ # @raise [Error] on a negative or non-numeric -j
198
+ def concurrency(options)
199
+ value = options[:concurrency] || Etc.nprocessors
200
+ Integer(value).tap { raise Error, "--concurrency must be 0 or more, got #{value}" if it.negative? }
201
+ rescue ArgumentError, TypeError
202
+ raise Error, "--concurrency must be a whole number, got #{value.inspect}"
203
+ end
204
+
189
205
  # @return [Warnings] what this command has held back from the screen
190
206
  def warnings = @warnings ||= Warnings.new
191
207
 
@@ -25,7 +25,7 @@ module Agent
25
25
 
26
26
  setup!(contenders, options)
27
27
  runs = datasets.flat_map { |name| contenders.map { experiment(it, config, options, dataset: name) } }
28
- summaries = execute(runs)
28
+ summaries = execute(runs, concurrency: concurrency(options))
29
29
  report(summaries, output: options[:output], open: options[:open]) do
30
30
  summaries.each { breakdown(it, titled: summaries.size > 1) }
31
31
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Agent
4
4
  module Evals
5
- VERSION = "0.1.1"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
data/lib/agent/evals.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "etc"
3
4
  require "json"
4
5
  require "dry/cli"
5
6
  require "dry/cli/help"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agent-evals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul