benchmax 0.1.2.dev36__tar.gz → 0.2.0__tar.gz
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.
- benchmax-0.2.0/.gitignore +81 -0
- benchmax-0.2.0/PKG-INFO +193 -0
- benchmax-0.2.0/README.md +178 -0
- benchmax-0.2.0/pyproject.toml +35 -0
- benchmax-0.2.0/pytest.ini +36 -0
- benchmax-0.2.0/src/benchmax/auth.py +109 -0
- benchmax-0.2.0/src/benchmax/bundle.py +1024 -0
- benchmax-0.2.0/src/benchmax/envs/README.md +25 -0
- benchmax-0.2.0/src/benchmax/envs/__init__.py +46 -0
- benchmax-0.2.0/src/benchmax/envs/base/README.md +74 -0
- benchmax-0.2.0/src/benchmax/envs/base/__init__.py +14 -0
- benchmax-0.2.0/src/benchmax/envs/base/dataset.py +75 -0
- benchmax-0.2.0/src/benchmax/envs/base/env.py +544 -0
- benchmax-0.2.0/src/benchmax/envs/base/openai_types.py +18 -0
- benchmax-0.2.0/src/benchmax/envs/dataset.py +25 -0
- benchmax-0.2.0/src/benchmax/envs/environment.py +381 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/README.md +156 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/__init__.py +25 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/bundled_agent.py +286 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/credentials.py +215 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/dataset.py +158 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/dep_check.py +17 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/env.py +631 -0
- benchmax-0.2.0/src/benchmax/envs/harbor/types.py +79 -0
- benchmax-0.2.0/src/benchmax/envs/identity.py +63 -0
- benchmax-0.2.0/src/benchmax/envs/logging.py +90 -0
- benchmax-0.2.0/src/benchmax/envs/shared_types.py +144 -0
- benchmax-0.2.0/src/benchmax/rewards/__init__.py +80 -0
- benchmax-0.2.0/src/benchmax/rewards/adaptive.py +238 -0
- benchmax-0.2.0/src/benchmax/rewards/deterministic.py +175 -0
- benchmax-0.2.0/src/benchmax/rewards/diversity.py +213 -0
- benchmax-0.2.0/src/benchmax/rewards/judge.py +191 -0
- {benchmax-0.1.2.dev36/src/benchmax/rubrics → benchmax-0.2.0/src/benchmax/rewards}/prompts.py +166 -0
- benchmax-0.2.0/src/benchmax/rewards/rubric.py +418 -0
- benchmax-0.2.0/src/benchmax/rewards/scoring.py +244 -0
- benchmax-0.2.0/tests/conftest.py +29 -0
- benchmax-0.2.0/tests/unit/bundle/test_artifact.py +181 -0
- benchmax-0.2.0/tests/unit/bundle/test_source_capture.py +593 -0
- benchmax-0.2.0/tests/unit/envs/test_base_dataset.py +62 -0
- benchmax-0.2.0/tests/unit/envs/test_base_env_group.py +912 -0
- benchmax-0.2.0/tests/unit/envs/test_contract_types.py +61 -0
- benchmax-0.2.0/tests/unit/envs/test_environment_group.py +465 -0
- benchmax-0.2.0/tests/unit/envs/test_example_id.py +46 -0
- benchmax-0.2.0/tests/unit/fakes/model_server.py +179 -0
- benchmax-0.2.0/tests/unit/harbor/test_bundled_agent.py +328 -0
- benchmax-0.2.0/tests/unit/harbor/test_harbor_dataset.py +210 -0
- benchmax-0.2.0/tests/unit/harbor/test_harbor_env.py +855 -0
- benchmax-0.2.0/tests/unit/rewards/conftest.py +60 -0
- benchmax-0.2.0/tests/unit/rewards/test_adaptive.py +134 -0
- benchmax-0.2.0/tests/unit/rewards/test_deterministic.py +81 -0
- benchmax-0.2.0/tests/unit/rewards/test_diversity.py +134 -0
- benchmax-0.2.0/tests/unit/rewards/test_diversity_env.py +238 -0
- benchmax-0.2.0/tests/unit/rewards/test_judge.py +117 -0
- benchmax-0.2.0/tests/unit/rewards/test_rubric.py +185 -0
- benchmax-0.2.0/tests/unit/rewards/test_rubric_rewards.py +125 -0
- benchmax-0.2.0/tests/unit/test_auth.py +48 -0
- benchmax-0.1.2.dev36/LICENSE +0 -201
- benchmax-0.1.2.dev36/PKG-INFO +0 -77
- benchmax-0.1.2.dev36/README.md +0 -21
- benchmax-0.1.2.dev36/pyproject.toml +0 -89
- benchmax-0.1.2.dev36/setup.cfg +0 -4
- benchmax-0.1.2.dev36/src/benchmax/bundle.py +0 -377
- benchmax-0.1.2.dev36/src/benchmax/cli/__init__.py +0 -73
- benchmax-0.1.2.dev36/src/benchmax/cli/_auth.py +0 -65
- benchmax-0.1.2.dev36/src/benchmax/cli/_client.py +0 -49
- benchmax-0.1.2.dev36/src/benchmax/cli/_output.py +0 -151
- benchmax-0.1.2.dev36/src/benchmax/cli/_preflight.py +0 -104
- benchmax-0.1.2.dev36/src/benchmax/cli/_project.py +0 -188
- benchmax-0.1.2.dev36/src/benchmax/cli/_providers.py +0 -60
- benchmax-0.1.2.dev36/src/benchmax/cli/control.py +0 -28
- benchmax-0.1.2.dev36/src/benchmax/cli/corpus.py +0 -330
- benchmax-0.1.2.dev36/src/benchmax/cli/data.py +0 -562
- benchmax-0.1.2.dev36/src/benchmax/cli/dataview.py +0 -436
- benchmax-0.1.2.dev36/src/benchmax/cli/doctor.py +0 -110
- benchmax-0.1.2.dev36/src/benchmax/cli/help.py +0 -233
- benchmax-0.1.2.dev36/src/benchmax/cli/launch.py +0 -445
- benchmax-0.1.2.dev36/src/benchmax/cli/runs.py +0 -392
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/CLAUDE.md +0 -162
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/STARTER.md +0 -98
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/generic_eval_dataset.jsonl +0 -2
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/generic_main.py +0 -301
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/generic_train_dataset.jsonl +0 -3
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/rag_eval_dataset.jsonl +0 -1
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/rag_main.py +0 -508
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/rag_train_dataset.jsonl +0 -2
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/skills/design-environment/SKILL.md +0 -380
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/skills/generate-data/SKILL.md +0 -195
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/skills/launch-run/SKILL.md +0 -130
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/skills/verify-environment/SKILL.md +0 -228
- benchmax-0.1.2.dev36/src/benchmax/cli/scaffold/skills/view-progress/SKILL.md +0 -173
- benchmax-0.1.2.dev36/src/benchmax/cli/setup.py +0 -360
- benchmax-0.1.2.dev36/src/benchmax/cli/templates/viewer.html +0 -485
- benchmax-0.1.2.dev36/src/benchmax/cli/validate.py +0 -775
- benchmax-0.1.2.dev36/src/benchmax/config.py +0 -55
- benchmax-0.1.2.dev36/src/benchmax/envs/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/envs/base_env.py +0 -254
- benchmax-0.1.2.dev36/src/benchmax/envs/crm/crm_env.py +0 -107
- benchmax-0.1.2.dev36/src/benchmax/envs/crm/workdir/reward_fn.py +0 -167
- benchmax-0.1.2.dev36/src/benchmax/envs/example_id.py +0 -149
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/data_utils.py +0 -28
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/excel_env.py +0 -230
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/workdir/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/workdir/excel_code_runner_mcp.py +0 -60
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/workdir/excel_utils.py +0 -254
- benchmax-0.1.2.dev36/src/benchmax/envs/excel/workdir/reward_fn.py +0 -56
- benchmax-0.1.2.dev36/src/benchmax/envs/logging.py +0 -122
- benchmax-0.1.2.dev36/src/benchmax/envs/math/math_env.py +0 -72
- benchmax-0.1.2.dev36/src/benchmax/envs/math/workdir/reward_fn.py +0 -46
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/__init__.py +0 -12
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/example_workdir/demo_mcp_server.py +0 -131
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/example_workdir/reward_fn.py +0 -135
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/parallel_mcp_env.py +0 -604
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/__init__.py +0 -20
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/base_provisioner.py +0 -50
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/local_provisioner.py +0 -319
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/manual_provisioner.py +0 -70
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/skypilot_provisioner.py +0 -222
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/provisioners/utils.py +0 -106
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/proxy_server.py +0 -471
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/server_pool.py +0 -493
- benchmax-0.1.2.dev36/src/benchmax/envs/mcp/utils.py +0 -217
- benchmax-0.1.2.dev36/src/benchmax/envs/postgres_search/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/envs/postgres_search/linker_env.py +0 -237
- benchmax-0.1.2.dev36/src/benchmax/envs/postgres_search/search_env.py +0 -671
- benchmax-0.1.2.dev36/src/benchmax/envs/reward_helpers.py +0 -215
- benchmax-0.1.2.dev36/src/benchmax/envs/telestich/example.py +0 -663
- benchmax-0.1.2.dev36/src/benchmax/envs/telestich/telestich_env.py +0 -1320
- benchmax-0.1.2.dev36/src/benchmax/envs/types.py +0 -137
- benchmax-0.1.2.dev36/src/benchmax/envs/wikipedia/utils.py +0 -95
- benchmax-0.1.2.dev36/src/benchmax/envs/wikipedia/wiki_env.py +0 -274
- benchmax-0.1.2.dev36/src/benchmax/multi_model/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/multi_model/caller.py +0 -504
- benchmax-0.1.2.dev36/src/benchmax/multi_model/clients.py +0 -144
- benchmax-0.1.2.dev36/src/benchmax/multi_model/example_usage.py +0 -325
- benchmax-0.1.2.dev36/src/benchmax/multi_model/inspector.py +0 -140
- benchmax-0.1.2.dev36/src/benchmax/multi_model/models.py +0 -108
- benchmax-0.1.2.dev36/src/benchmax/multi_model/pricing.py +0 -67
- benchmax-0.1.2.dev36/src/benchmax/platform/__init__.py +0 -25
- benchmax-0.1.2.dev36/src/benchmax/platform/browser.py +0 -32
- benchmax-0.1.2.dev36/src/benchmax/platform/client.py +0 -1596
- benchmax-0.1.2.dev36/src/benchmax/platform/credentials.py +0 -379
- benchmax-0.1.2.dev36/src/benchmax/platform/device_auth.py +0 -81
- benchmax-0.1.2.dev36/src/benchmax/platform/exceptions.py +0 -46
- benchmax-0.1.2.dev36/src/benchmax/platform/login.py +0 -70
- benchmax-0.1.2.dev36/src/benchmax/platform/training_run.py +0 -173
- benchmax-0.1.2.dev36/src/benchmax/platform/validation.py +0 -960
- benchmax-0.1.2.dev36/src/benchmax/prompts/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/prompts/tools.py +0 -92
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/email.py +0 -793
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/inspector.py +0 -230
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/markdown.py +0 -347
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/models.py +0 -253
- benchmax-0.1.2.dev36/src/benchmax/rag/chunkers/storage.py +0 -78
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/__init__.py +0 -1
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/client.py +0 -536
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/files.py +0 -162
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/filter_mapper.py +0 -149
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/search.py +0 -207
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/chroma/source.py +0 -792
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/embed.py +0 -54
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/files.py +0 -159
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/filter_mapper.py +0 -194
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/index_client.py +0 -460
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/search.py +0 -128
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/pinecone/source.py +0 -559
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/client.py +0 -799
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/exceptions.py +0 -53
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/filter_mapper.py +0 -119
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/models.py +0 -63
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/search.py +0 -113
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/postgres/source.py +0 -479
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_client.py +0 -62
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_schema/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_schema/builders.py +0 -58
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_schema/dsl_parser.py +0 -47
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_schema/search_exceptions.py +0 -63
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/search_schema/search_types.py +0 -176
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/source.py +0 -127
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/files.py +0 -175
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/filter_mapper.py +0 -139
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/namespace.py +0 -344
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/search.py +0 -215
- benchmax-0.1.2.dev36/src/benchmax/rag/corpus/turbopuffer/source.py +0 -722
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/clean_bodies.py +0 -513
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/dedupe.py +0 -799
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/filter_automated_email_qas.py +0 -320
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/filter_automated_emails.py +0 -560
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/mbox.py +0 -257
- benchmax-0.1.2.dev36/src/benchmax/rag/preprocess/email/schema.py +0 -180
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/__init__.py +0 -64
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/anchor_selector.py +0 -17
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/auto_tune.py +0 -255
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/batch_processor.py +0 -500
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/checkpoint.py +0 -294
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/corpus_capabilities.py +0 -94
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/corpus_profile.py +0 -1688
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/__init__.py +0 -21
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/deterministic_guards.py +0 -225
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/env_rollout.py +0 -288
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/grounding_llm.py +0 -589
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/hop_count_validity.py +0 -1078
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/quality_gate.py +0 -243
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/filters/retrieval_llm.py +0 -896
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/formatters/__init__.py +0 -5
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/formatters/train_eval.py +0 -123
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/generated_qa.py +0 -125
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/generators/__init__.py +0 -5
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/generators/direct_llm.py +0 -765
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/helpers.py +0 -133
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/metadata_linker.py +0 -940
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/metrics.py +0 -95
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/models.py +0 -36
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/pipeline.py +0 -2748
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/pipeline_config.py +0 -1204
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/protocols.py +0 -66
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/query_rewriter.py +0 -149
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/response_parsers.py +0 -63
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/retrieval_query.py +0 -76
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/scoring.py +0 -114
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/search_agent_linker.py +0 -662
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/storage.py +0 -142
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/style_controls.py +0 -230
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/transformers/__init__.py +0 -7
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/transformers/base.py +0 -125
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/transformers/dedup.py +0 -195
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/wiki_builder.py +0 -539
- benchmax-0.1.2.dev36/src/benchmax/rag/qa_generation/wiki_chunk_linker.py +0 -331
- benchmax-0.1.2.dev36/src/benchmax/rewards/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/rewards/diversity.py +0 -305
- benchmax-0.1.2.dev36/src/benchmax/rubrics/__init__.py +0 -17
- benchmax-0.1.2.dev36/src/benchmax/rubrics/_utils.py +0 -51
- benchmax-0.1.2.dev36/src/benchmax/rubrics/adaptive.py +0 -137
- benchmax-0.1.2.dev36/src/benchmax/rubrics/cache.py +0 -178
- benchmax-0.1.2.dev36/src/benchmax/rubrics/reward_fns.py +0 -349
- benchmax-0.1.2.dev36/src/benchmax/rubrics/rubric.py +0 -463
- benchmax-0.1.2.dev36/src/benchmax/traces/__init__.py +0 -8
- benchmax-0.1.2.dev36/src/benchmax/traces/adapter.py +0 -351
- benchmax-0.1.2.dev36/src/benchmax/traces/braintrust/__init__.py +0 -0
- benchmax-0.1.2.dev36/src/benchmax/traces/braintrust/adapter.py +0 -322
- benchmax-0.1.2.dev36/src/benchmax/traces/braintrust/message_extraction.py +0 -245
- benchmax-0.1.2.dev36/src/benchmax/traces/http.py +0 -90
- benchmax-0.1.2.dev36/src/benchmax/traces/pipeline.py +0 -278
- benchmax-0.1.2.dev36/src/benchmax/traces/pivot.py +0 -664
- benchmax-0.1.2.dev36/src/benchmax/traces/processing.py +0 -776
- benchmax-0.1.2.dev36/src/benchmax/traces/registry.py +0 -32
- benchmax-0.1.2.dev36/src/benchmax/utils/__init__.py +0 -14
- benchmax-0.1.2.dev36/src/benchmax/utils/checkpoint.py +0 -87
- benchmax-0.1.2.dev36/src/benchmax.egg-info/PKG-INFO +0 -77
- benchmax-0.1.2.dev36/src/benchmax.egg-info/SOURCES.txt +0 -204
- benchmax-0.1.2.dev36/src/benchmax.egg-info/dependency_links.txt +0 -1
- benchmax-0.1.2.dev36/src/benchmax.egg-info/entry_points.txt +0 -2
- benchmax-0.1.2.dev36/src/benchmax.egg-info/requires.txt +0 -55
- benchmax-0.1.2.dev36/src/benchmax.egg-info/top_level.txt +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual Environments
|
|
24
|
+
.env
|
|
25
|
+
.venv
|
|
26
|
+
.python-version
|
|
27
|
+
env/
|
|
28
|
+
venv/
|
|
29
|
+
ENV/
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
*.swo
|
|
36
|
+
|
|
37
|
+
# Distribution / packaging
|
|
38
|
+
.Python
|
|
39
|
+
build/
|
|
40
|
+
develop-eggs/
|
|
41
|
+
dist/
|
|
42
|
+
downloads/
|
|
43
|
+
eggs/
|
|
44
|
+
.eggs/
|
|
45
|
+
lib/
|
|
46
|
+
lib64/
|
|
47
|
+
parts/
|
|
48
|
+
sdist/
|
|
49
|
+
var/
|
|
50
|
+
wheels/
|
|
51
|
+
*.egg-info/
|
|
52
|
+
.installed.cfg
|
|
53
|
+
*.egg
|
|
54
|
+
|
|
55
|
+
# Unit test / coverage reports
|
|
56
|
+
htmlcov/
|
|
57
|
+
.tox/
|
|
58
|
+
.coverage
|
|
59
|
+
.coverage.*
|
|
60
|
+
.cache
|
|
61
|
+
nosetests.xml
|
|
62
|
+
coverage.xml
|
|
63
|
+
*.cover
|
|
64
|
+
.hypothesis/
|
|
65
|
+
.pytest_cache/
|
|
66
|
+
|
|
67
|
+
# mypy
|
|
68
|
+
.mypy_cache/
|
|
69
|
+
|
|
70
|
+
# Jupyter Notebook
|
|
71
|
+
.ipynb_checkpoints
|
|
72
|
+
|
|
73
|
+
# macOS
|
|
74
|
+
.DS_Store
|
|
75
|
+
|
|
76
|
+
# Poetry
|
|
77
|
+
poetry.lock
|
|
78
|
+
|
|
79
|
+
# Generated workspaces
|
|
80
|
+
workspaces/
|
|
81
|
+
outputs/
|
benchmax-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: benchmax
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Platform-independent runtime for grouped LLM environments
|
|
5
|
+
Author: BenchMax Authors
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: ==3.12.*
|
|
9
|
+
Requires-Dist: cloudpickle>=3.0.0
|
|
10
|
+
Requires-Dist: openai>=2.15.0
|
|
11
|
+
Requires-Dist: packaging>=24.0
|
|
12
|
+
Provides-Extra: harbor
|
|
13
|
+
Requires-Dist: harbor<0.19,>=0.18.0; extra == 'harbor'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# BenchMax
|
|
17
|
+
|
|
18
|
+
BenchMax is a platform-independent runtime for defining and running reinforcement-
|
|
19
|
+
learning environments. It owns the execution contract, ordered datasets, stable
|
|
20
|
+
example identities, reward helpers and bundling. It has no dependency on any
|
|
21
|
+
training platform.
|
|
22
|
+
|
|
23
|
+
Python 3.12 is required.
|
|
24
|
+
|
|
25
|
+
## Define an environment
|
|
26
|
+
|
|
27
|
+
Most environments extend `BaseEnv` and declare their complete reward shape:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
from benchmax.envs import BaseEnv, BaseRollout, DatasetSplit, JsonlDataset
|
|
33
|
+
from benchmax.rewards import extract_completion_text
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AnswerEnv(BaseEnv):
|
|
37
|
+
reward_keys = ("correct",)
|
|
38
|
+
max_turns = 1
|
|
39
|
+
|
|
40
|
+
async def create_dataset(
|
|
41
|
+
self, split: DatasetSplit, base_dir: Path
|
|
42
|
+
) -> JsonlDataset:
|
|
43
|
+
return JsonlDataset(base_dir / f"{split}.jsonl", row_to_example=...)
|
|
44
|
+
|
|
45
|
+
async def compute_reward(self, rollout: BaseRollout) -> dict[str, float]:
|
|
46
|
+
answer = extract_completion_text(rollout.messages)
|
|
47
|
+
return {"correct": float(answer == rollout.example_args["answer"])}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`Dataset` is a fixed-order base class. Concrete datasets provide stable
|
|
51
|
+
`Example` objects and may keep lightweight references in each payload instead of
|
|
52
|
+
materializing large data in memory.
|
|
53
|
+
|
|
54
|
+
Each `RolloutRequest` carries a `split` (`"train"` by default) so custom
|
|
55
|
+
`run_rollout`/`run_group` implementations can tell training traffic from
|
|
56
|
+
evaluation traffic without out-of-band state.
|
|
57
|
+
|
|
58
|
+
`reward_keys` is authoritative. A successful rollout must return exactly those
|
|
59
|
+
keys. Operational failures keep the same shape with every value set to zero,
|
|
60
|
+
record the reason in `termination_reason`, and are logged without cancelling
|
|
61
|
+
successful siblings. Reward hooks run user code, so their defects settle the
|
|
62
|
+
same way under `reward_error` (per rollout) or `group_reward_error` (whole
|
|
63
|
+
group) instead of crashing a run; execution-contract violations such as
|
|
64
|
+
malformed requests or a broken reward schema still fail loudly after the
|
|
65
|
+
sibling group settles.
|
|
66
|
+
|
|
67
|
+
See the [BaseEnv guide](src/benchmax/envs/base/README.md) and
|
|
68
|
+
[Harbor adapter guide](src/benchmax/envs/harbor/README.md).
|
|
69
|
+
|
|
70
|
+
## Define judge-backed rewards
|
|
71
|
+
|
|
72
|
+
Judge configuration is one serializable value shared by rubric, adaptive-rubric,
|
|
73
|
+
and semantic-diversity rewards. Authentication is resolved immediately before
|
|
74
|
+
each model call; bundles carry an `InjectedAuth` reference, never its token.
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from benchmax.auth import InjectedAuth
|
|
78
|
+
from benchmax.rewards import Judge, Rubric, score_rubrics
|
|
79
|
+
|
|
80
|
+
judge = Judge(
|
|
81
|
+
model="judge-model",
|
|
82
|
+
base_url="https://models.example/v1",
|
|
83
|
+
auth=InjectedAuth("judge"),
|
|
84
|
+
)
|
|
85
|
+
rubrics = [
|
|
86
|
+
Rubric("Correctness", "The answer is factually correct."),
|
|
87
|
+
Rubric(
|
|
88
|
+
"Fabrication",
|
|
89
|
+
"The answer invents unsupported facts.",
|
|
90
|
+
polarity="negative",
|
|
91
|
+
),
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
rewards = await score_rubrics(
|
|
95
|
+
rollout_id,
|
|
96
|
+
completion,
|
|
97
|
+
ground_truth=reference,
|
|
98
|
+
rubrics=rubrics,
|
|
99
|
+
question=question,
|
|
100
|
+
judge=judge,
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`InjectedAuth("judge")` is a named reference; the runtime binds the real
|
|
105
|
+
provider for that name with `bind_model_auth`. Prefer it whenever the runtime
|
|
106
|
+
supplies the credential. For your own external judge endpoint, pass
|
|
107
|
+
`auth=StaticBearerAuth(api_key)` directly; note the key is then pickled into
|
|
108
|
+
the bundle.
|
|
109
|
+
|
|
110
|
+
`evaluate_single_rubric` and `evaluate_rubric_ranking` return typed results.
|
|
111
|
+
`score_rubrics`, `score_group_rubrics`, and `rank_group_rubrics` turn those
|
|
112
|
+
results into reward maps. Empty completions keep the declared rubric reward
|
|
113
|
+
shape and receive zeros without calling the judge. Invalid or out-of-set judge
|
|
114
|
+
output raises `JudgeError` so the environment runtime can record an operational
|
|
115
|
+
failure instead of trusting a fabricated score.
|
|
116
|
+
|
|
117
|
+
Adaptive rubric state is explicit and caller-owned through `RubricCache`.
|
|
118
|
+
Diversity backends are explicit as well: use `NgramDiversityConfig` for local
|
|
119
|
+
single-linkage clustering or `LLMDiversityConfig(judge=judge)` for semantic
|
|
120
|
+
clustering.
|
|
121
|
+
|
|
122
|
+
The rewards package follows a deep-module design:
|
|
123
|
+
|
|
124
|
+
- Callers provide domain intent; modules own prompt structure, authentication
|
|
125
|
+
retries, parsing, score normalization, clustering, and cache keys.
|
|
126
|
+
- Related values use validated types such as `Judge`, `Rubric`, and
|
|
127
|
+
`RankingAnchor` instead of parallel parameters or loose dictionaries.
|
|
128
|
+
- Module names describe capabilities (`prompts`, `scoring`, `deterministic`),
|
|
129
|
+
not visibility or generic “helper” status.
|
|
130
|
+
- A new public abstraction should hide substantially more complexity than it
|
|
131
|
+
adds to the interface.
|
|
132
|
+
|
|
133
|
+
## Bundle an environment
|
|
134
|
+
|
|
135
|
+
Declare remote runtime dependencies at the script boundary:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from benchmax.bundle import bundle_digest, dump_bundle
|
|
139
|
+
|
|
140
|
+
bundle = dump_bundle(
|
|
141
|
+
AnswerEnv,
|
|
142
|
+
constructor_args={},
|
|
143
|
+
pip_dependencies=["httpx>=0.28,<0.29"],
|
|
144
|
+
)
|
|
145
|
+
print(bundle_digest(bundle))
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
BenchMax automatically captures project-local Python modules reachable from the
|
|
149
|
+
environment. Source from a different project is never captured implicitly: pass
|
|
150
|
+
its module object through `local_modules=` to include it, or list its installed
|
|
151
|
+
distribution in `pip_dependencies` to keep it as a remote reference. External
|
|
152
|
+
packages are never inferred from project metadata. Dependency declarations must
|
|
153
|
+
be valid PEP 508 strings; BenchMax canonicalizes and stores them as an immutable,
|
|
154
|
+
order-independent collection in bundle metadata. Declare each distribution once,
|
|
155
|
+
combining its constraints and extras in that declaration; repeated targets are
|
|
156
|
+
rejected instead of relying on resolver-specific conflict behavior.
|
|
157
|
+
|
|
158
|
+
Keep project-local imports at module scope so source capture can see them.
|
|
159
|
+
BenchMax refuses method-local imports of local source, including literal
|
|
160
|
+
`importlib.import_module(...)` calls, because reconstructed by-value modules do
|
|
161
|
+
not satisfy a later Python import. Runtime-computed dynamic import names cannot
|
|
162
|
+
be inferred; install those modules remotely and declare their distributions in
|
|
163
|
+
`pip_dependencies`.
|
|
164
|
+
|
|
165
|
+
BenchMax only prepares the bundle. Uploading it and launching a hosted run belong
|
|
166
|
+
to the platform integration chosen by the caller. `bundle_digest` is the
|
|
167
|
+
artifact identity for storage and caching; it covers both the exact pickle and
|
|
168
|
+
canonical metadata. Execution runtimes can call `validate_bundle_compatibility`
|
|
169
|
+
on metadata before installing dependencies or unpickling. The Python version
|
|
170
|
+
must match exactly and the BenchMax version must share the runtime's
|
|
171
|
+
major.minor series; patch releases load each other's bundles.
|
|
172
|
+
|
|
173
|
+
## Breaking-version policy
|
|
174
|
+
|
|
175
|
+
This reshuffle intentionally removes the old `benchmax.rubrics`,
|
|
176
|
+
`benchmax.envs.reward_helpers`, `benchmax.prompts`, and `FrozenDataset` import
|
|
177
|
+
surfaces. There are no compatibility aliases. Rebuild environments and bundles
|
|
178
|
+
against the new `benchmax.rewards` and `Dataset` APIs; a runtime that must execute
|
|
179
|
+
an older stored bundle must remain pinned to the older BenchMax version.
|
|
180
|
+
|
|
181
|
+
Rubric judges now enforce their declared score set. A binary rubric accepts only
|
|
182
|
+
`0` or `1`; include intermediate values explicitly in `score_map`, or use a
|
|
183
|
+
ranking reward when continuous relative scores are intended. An out-of-set judge
|
|
184
|
+
score is an operational `judge_error`, not a trusted reward.
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
uv run --project packages/benchmax pytest \
|
|
190
|
+
-c packages/benchmax/pytest.ini packages/benchmax/tests
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Apache 2.0 © 2026 CGFT Inc.
|
benchmax-0.2.0/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# BenchMax
|
|
2
|
+
|
|
3
|
+
BenchMax is a platform-independent runtime for defining and running reinforcement-
|
|
4
|
+
learning environments. It owns the execution contract, ordered datasets, stable
|
|
5
|
+
example identities, reward helpers and bundling. It has no dependency on any
|
|
6
|
+
training platform.
|
|
7
|
+
|
|
8
|
+
Python 3.12 is required.
|
|
9
|
+
|
|
10
|
+
## Define an environment
|
|
11
|
+
|
|
12
|
+
Most environments extend `BaseEnv` and declare their complete reward shape:
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from benchmax.envs import BaseEnv, BaseRollout, DatasetSplit, JsonlDataset
|
|
18
|
+
from benchmax.rewards import extract_completion_text
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AnswerEnv(BaseEnv):
|
|
22
|
+
reward_keys = ("correct",)
|
|
23
|
+
max_turns = 1
|
|
24
|
+
|
|
25
|
+
async def create_dataset(
|
|
26
|
+
self, split: DatasetSplit, base_dir: Path
|
|
27
|
+
) -> JsonlDataset:
|
|
28
|
+
return JsonlDataset(base_dir / f"{split}.jsonl", row_to_example=...)
|
|
29
|
+
|
|
30
|
+
async def compute_reward(self, rollout: BaseRollout) -> dict[str, float]:
|
|
31
|
+
answer = extract_completion_text(rollout.messages)
|
|
32
|
+
return {"correct": float(answer == rollout.example_args["answer"])}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`Dataset` is a fixed-order base class. Concrete datasets provide stable
|
|
36
|
+
`Example` objects and may keep lightweight references in each payload instead of
|
|
37
|
+
materializing large data in memory.
|
|
38
|
+
|
|
39
|
+
Each `RolloutRequest` carries a `split` (`"train"` by default) so custom
|
|
40
|
+
`run_rollout`/`run_group` implementations can tell training traffic from
|
|
41
|
+
evaluation traffic without out-of-band state.
|
|
42
|
+
|
|
43
|
+
`reward_keys` is authoritative. A successful rollout must return exactly those
|
|
44
|
+
keys. Operational failures keep the same shape with every value set to zero,
|
|
45
|
+
record the reason in `termination_reason`, and are logged without cancelling
|
|
46
|
+
successful siblings. Reward hooks run user code, so their defects settle the
|
|
47
|
+
same way under `reward_error` (per rollout) or `group_reward_error` (whole
|
|
48
|
+
group) instead of crashing a run; execution-contract violations such as
|
|
49
|
+
malformed requests or a broken reward schema still fail loudly after the
|
|
50
|
+
sibling group settles.
|
|
51
|
+
|
|
52
|
+
See the [BaseEnv guide](src/benchmax/envs/base/README.md) and
|
|
53
|
+
[Harbor adapter guide](src/benchmax/envs/harbor/README.md).
|
|
54
|
+
|
|
55
|
+
## Define judge-backed rewards
|
|
56
|
+
|
|
57
|
+
Judge configuration is one serializable value shared by rubric, adaptive-rubric,
|
|
58
|
+
and semantic-diversity rewards. Authentication is resolved immediately before
|
|
59
|
+
each model call; bundles carry an `InjectedAuth` reference, never its token.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from benchmax.auth import InjectedAuth
|
|
63
|
+
from benchmax.rewards import Judge, Rubric, score_rubrics
|
|
64
|
+
|
|
65
|
+
judge = Judge(
|
|
66
|
+
model="judge-model",
|
|
67
|
+
base_url="https://models.example/v1",
|
|
68
|
+
auth=InjectedAuth("judge"),
|
|
69
|
+
)
|
|
70
|
+
rubrics = [
|
|
71
|
+
Rubric("Correctness", "The answer is factually correct."),
|
|
72
|
+
Rubric(
|
|
73
|
+
"Fabrication",
|
|
74
|
+
"The answer invents unsupported facts.",
|
|
75
|
+
polarity="negative",
|
|
76
|
+
),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
rewards = await score_rubrics(
|
|
80
|
+
rollout_id,
|
|
81
|
+
completion,
|
|
82
|
+
ground_truth=reference,
|
|
83
|
+
rubrics=rubrics,
|
|
84
|
+
question=question,
|
|
85
|
+
judge=judge,
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`InjectedAuth("judge")` is a named reference; the runtime binds the real
|
|
90
|
+
provider for that name with `bind_model_auth`. Prefer it whenever the runtime
|
|
91
|
+
supplies the credential. For your own external judge endpoint, pass
|
|
92
|
+
`auth=StaticBearerAuth(api_key)` directly; note the key is then pickled into
|
|
93
|
+
the bundle.
|
|
94
|
+
|
|
95
|
+
`evaluate_single_rubric` and `evaluate_rubric_ranking` return typed results.
|
|
96
|
+
`score_rubrics`, `score_group_rubrics`, and `rank_group_rubrics` turn those
|
|
97
|
+
results into reward maps. Empty completions keep the declared rubric reward
|
|
98
|
+
shape and receive zeros without calling the judge. Invalid or out-of-set judge
|
|
99
|
+
output raises `JudgeError` so the environment runtime can record an operational
|
|
100
|
+
failure instead of trusting a fabricated score.
|
|
101
|
+
|
|
102
|
+
Adaptive rubric state is explicit and caller-owned through `RubricCache`.
|
|
103
|
+
Diversity backends are explicit as well: use `NgramDiversityConfig` for local
|
|
104
|
+
single-linkage clustering or `LLMDiversityConfig(judge=judge)` for semantic
|
|
105
|
+
clustering.
|
|
106
|
+
|
|
107
|
+
The rewards package follows a deep-module design:
|
|
108
|
+
|
|
109
|
+
- Callers provide domain intent; modules own prompt structure, authentication
|
|
110
|
+
retries, parsing, score normalization, clustering, and cache keys.
|
|
111
|
+
- Related values use validated types such as `Judge`, `Rubric`, and
|
|
112
|
+
`RankingAnchor` instead of parallel parameters or loose dictionaries.
|
|
113
|
+
- Module names describe capabilities (`prompts`, `scoring`, `deterministic`),
|
|
114
|
+
not visibility or generic “helper” status.
|
|
115
|
+
- A new public abstraction should hide substantially more complexity than it
|
|
116
|
+
adds to the interface.
|
|
117
|
+
|
|
118
|
+
## Bundle an environment
|
|
119
|
+
|
|
120
|
+
Declare remote runtime dependencies at the script boundary:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from benchmax.bundle import bundle_digest, dump_bundle
|
|
124
|
+
|
|
125
|
+
bundle = dump_bundle(
|
|
126
|
+
AnswerEnv,
|
|
127
|
+
constructor_args={},
|
|
128
|
+
pip_dependencies=["httpx>=0.28,<0.29"],
|
|
129
|
+
)
|
|
130
|
+
print(bundle_digest(bundle))
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
BenchMax automatically captures project-local Python modules reachable from the
|
|
134
|
+
environment. Source from a different project is never captured implicitly: pass
|
|
135
|
+
its module object through `local_modules=` to include it, or list its installed
|
|
136
|
+
distribution in `pip_dependencies` to keep it as a remote reference. External
|
|
137
|
+
packages are never inferred from project metadata. Dependency declarations must
|
|
138
|
+
be valid PEP 508 strings; BenchMax canonicalizes and stores them as an immutable,
|
|
139
|
+
order-independent collection in bundle metadata. Declare each distribution once,
|
|
140
|
+
combining its constraints and extras in that declaration; repeated targets are
|
|
141
|
+
rejected instead of relying on resolver-specific conflict behavior.
|
|
142
|
+
|
|
143
|
+
Keep project-local imports at module scope so source capture can see them.
|
|
144
|
+
BenchMax refuses method-local imports of local source, including literal
|
|
145
|
+
`importlib.import_module(...)` calls, because reconstructed by-value modules do
|
|
146
|
+
not satisfy a later Python import. Runtime-computed dynamic import names cannot
|
|
147
|
+
be inferred; install those modules remotely and declare their distributions in
|
|
148
|
+
`pip_dependencies`.
|
|
149
|
+
|
|
150
|
+
BenchMax only prepares the bundle. Uploading it and launching a hosted run belong
|
|
151
|
+
to the platform integration chosen by the caller. `bundle_digest` is the
|
|
152
|
+
artifact identity for storage and caching; it covers both the exact pickle and
|
|
153
|
+
canonical metadata. Execution runtimes can call `validate_bundle_compatibility`
|
|
154
|
+
on metadata before installing dependencies or unpickling. The Python version
|
|
155
|
+
must match exactly and the BenchMax version must share the runtime's
|
|
156
|
+
major.minor series; patch releases load each other's bundles.
|
|
157
|
+
|
|
158
|
+
## Breaking-version policy
|
|
159
|
+
|
|
160
|
+
This reshuffle intentionally removes the old `benchmax.rubrics`,
|
|
161
|
+
`benchmax.envs.reward_helpers`, `benchmax.prompts`, and `FrozenDataset` import
|
|
162
|
+
surfaces. There are no compatibility aliases. Rebuild environments and bundles
|
|
163
|
+
against the new `benchmax.rewards` and `Dataset` APIs; a runtime that must execute
|
|
164
|
+
an older stored bundle must remain pinned to the older BenchMax version.
|
|
165
|
+
|
|
166
|
+
Rubric judges now enforce their declared score set. A binary rubric accepts only
|
|
167
|
+
`0` or `1`; include intermediate values explicitly in `score_map`, or use a
|
|
168
|
+
ranking reward when continuous relative scores are intended. An out-of-set judge
|
|
169
|
+
score is an operational `judge_error`, not a trusted reward.
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv run --project packages/benchmax pytest \
|
|
175
|
+
-c packages/benchmax/pytest.ini packages/benchmax/tests
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Apache 2.0 © 2026 CGFT Inc.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "benchmax"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Platform-independent runtime for grouped LLM environments"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "BenchMax Authors" }]
|
|
7
|
+
requires-python = "==3.12.*"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"cloudpickle>=3.0.0",
|
|
10
|
+
"openai>=2.15.0",
|
|
11
|
+
"packaging>=24.0",
|
|
12
|
+
]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["hatchling>=1.27"]
|
|
20
|
+
build-backend = "hatchling.build"
|
|
21
|
+
|
|
22
|
+
[tool.hatch.build.targets.wheel]
|
|
23
|
+
packages = ["src/benchmax"]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
harbor = ["harbor>=0.18.0,<0.19"]
|
|
27
|
+
|
|
28
|
+
[dependency-groups]
|
|
29
|
+
dev = [
|
|
30
|
+
"harbor>=0.18.0,<0.19",
|
|
31
|
+
"pytest>=8.4.2",
|
|
32
|
+
"pytest-asyncio>=1.2.0",
|
|
33
|
+
"python-dotenv>=1.2.1",
|
|
34
|
+
"ruff>=0.14.2",
|
|
35
|
+
]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[pytest]
|
|
2
|
+
# Pytest configuration for benchmax
|
|
3
|
+
pythonpath = .
|
|
4
|
+
|
|
5
|
+
testpaths = tests
|
|
6
|
+
|
|
7
|
+
# Test discovery
|
|
8
|
+
python_files = test_*.py
|
|
9
|
+
python_classes = Test*
|
|
10
|
+
python_functions = test_*
|
|
11
|
+
|
|
12
|
+
# Asyncio mode
|
|
13
|
+
asyncio_mode = auto
|
|
14
|
+
|
|
15
|
+
# Markers
|
|
16
|
+
markers =
|
|
17
|
+
slow: Slow-running tests (deselect with '-m "not slow"')
|
|
18
|
+
remote: marks tests that require remote resources (deselect with '-m "not remote"')
|
|
19
|
+
unit: Fast, isolated tests
|
|
20
|
+
integration: Integration tests that hit live external APIs (require credentials; run with -m integration)
|
|
21
|
+
|
|
22
|
+
# Default deselection to speed up CI runs
|
|
23
|
+
addopts = -m "not slow and not remote and not integration" --import-mode=importlib
|
|
24
|
+
|
|
25
|
+
# Logging
|
|
26
|
+
log_cli = false
|
|
27
|
+
log_cli_level = INFO
|
|
28
|
+
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s
|
|
29
|
+
log_cli_date_format = %Y-%m-%d %H:%M:%S
|
|
30
|
+
|
|
31
|
+
# Warnings
|
|
32
|
+
filterwarnings =
|
|
33
|
+
ignore::DeprecationWarning
|
|
34
|
+
ignore::PendingDeprecationWarning
|
|
35
|
+
|
|
36
|
+
minversion = 7.0
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Explicit, call-time authentication for model requests.
|
|
2
|
+
|
|
3
|
+
BenchMax defines only the runtime contract. Platform packages and execution
|
|
4
|
+
runtimes provide concrete credential sources and bind injected credentials.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterator, Mapping
|
|
10
|
+
from contextlib import contextmanager
|
|
11
|
+
from contextvars import ContextVar
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import Protocol, runtime_checkable
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"InjectedAuth",
|
|
17
|
+
"ModelAuth",
|
|
18
|
+
"ModelRequestContext",
|
|
19
|
+
"StaticBearerAuth",
|
|
20
|
+
"bind_model_auth",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class ModelRequestContext:
|
|
26
|
+
"""Identity of the model request about to be authorized."""
|
|
27
|
+
|
|
28
|
+
base_url: str
|
|
29
|
+
model: str
|
|
30
|
+
rollout_id: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@runtime_checkable
|
|
34
|
+
class ModelAuth(Protocol):
|
|
35
|
+
"""Return headers immediately before each model HTTP request."""
|
|
36
|
+
|
|
37
|
+
async def headers_for_request(
|
|
38
|
+
self,
|
|
39
|
+
context: ModelRequestContext,
|
|
40
|
+
) -> Mapping[str, str]: ...
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class StaticBearerAuth:
|
|
45
|
+
"""Explicit bearer authentication for providers with a stable API key."""
|
|
46
|
+
|
|
47
|
+
token: str
|
|
48
|
+
|
|
49
|
+
def __post_init__(self) -> None:
|
|
50
|
+
if not isinstance(self.token, str) or not self.token:
|
|
51
|
+
raise ValueError("bearer token must be a non-empty string")
|
|
52
|
+
|
|
53
|
+
async def headers_for_request(
|
|
54
|
+
self,
|
|
55
|
+
context: ModelRequestContext,
|
|
56
|
+
) -> Mapping[str, str]:
|
|
57
|
+
del context
|
|
58
|
+
return {"Authorization": f"Bearer {self.token}"}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
_BOUND_MODEL_AUTH: ContextVar[Mapping[str, ModelAuth] | None] = ContextVar(
|
|
62
|
+
"benchmax_bound_model_auth",
|
|
63
|
+
default=None,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass(frozen=True, slots=True)
|
|
68
|
+
class InjectedAuth:
|
|
69
|
+
"""Serializable reference to authentication supplied by the runtime."""
|
|
70
|
+
|
|
71
|
+
name: str
|
|
72
|
+
|
|
73
|
+
def __post_init__(self) -> None:
|
|
74
|
+
if not isinstance(self.name, str) or not self.name.strip():
|
|
75
|
+
raise ValueError("injected auth name must be a non-empty string")
|
|
76
|
+
|
|
77
|
+
async def headers_for_request(
|
|
78
|
+
self,
|
|
79
|
+
context: ModelRequestContext,
|
|
80
|
+
) -> Mapping[str, str]:
|
|
81
|
+
providers = _BOUND_MODEL_AUTH.get()
|
|
82
|
+
provider = providers.get(self.name) if providers is not None else None
|
|
83
|
+
if provider is None:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
f"No runtime model-auth provider was injected for {self.name!r}."
|
|
86
|
+
)
|
|
87
|
+
if isinstance(provider, InjectedAuth):
|
|
88
|
+
raise RuntimeError(
|
|
89
|
+
f"Injected model-auth provider {self.name!r} cannot reference "
|
|
90
|
+
"another InjectedAuth."
|
|
91
|
+
)
|
|
92
|
+
return await provider.headers_for_request(context)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@contextmanager
|
|
96
|
+
def bind_model_auth(providers: Mapping[str, ModelAuth]) -> Iterator[None]:
|
|
97
|
+
"""Bind runtime providers for the current async execution context."""
|
|
98
|
+
|
|
99
|
+
normalized = dict(providers)
|
|
100
|
+
for name, provider in normalized.items():
|
|
101
|
+
if not isinstance(name, str) or not name.strip():
|
|
102
|
+
raise ValueError("model-auth provider names must be non-empty strings")
|
|
103
|
+
if not isinstance(provider, ModelAuth):
|
|
104
|
+
raise TypeError(f"model-auth provider {name!r} does not implement ModelAuth")
|
|
105
|
+
token = _BOUND_MODEL_AUTH.set(normalized)
|
|
106
|
+
try:
|
|
107
|
+
yield
|
|
108
|
+
finally:
|
|
109
|
+
_BOUND_MODEL_AUTH.reset(token)
|