|
| 1 | +# Repository Instructions |
| 2 | + |
| 3 | +## Shared LLM Registry |
| 4 | + |
| 5 | +This package targets Python 3.14. Black is configured with |
| 6 | +`target-version = ["py314"]`; do not broaden `requires-python` without first |
| 7 | +checking that formatted code remains valid for the older target. |
| 8 | + |
| 9 | +## Local Development Setup |
| 10 | + |
| 11 | +Use Python 3.14 for local development: |
| 12 | + |
| 13 | +```bash |
| 14 | +python3.14 -m venv .venv |
| 15 | +source .venv/bin/activate |
| 16 | +python -m pip install --upgrade pip |
| 17 | +python -m pip install -r requirements.txt |
| 18 | +``` |
| 19 | + |
| 20 | +`requirements.txt` delegates to `.[dev]`; it installs this package and the dev |
| 21 | +tools from `pyproject.toml` without editable mode. |
| 22 | + |
| 23 | +When another repo needs local utils changes during development, use that repo's |
| 24 | +virtual environment and install utils explicitly in editable mode, for example: |
| 25 | + |
| 26 | +```bash |
| 27 | +python -m pip install -e ../utils |
| 28 | +``` |
| 29 | + |
| 30 | +Do not add local relative paths to another repo's requirements files. Those |
| 31 | +files should use the deployed git pin when ready to deploy. |
| 32 | + |
| 33 | +The shared LLM registry has two layers: |
| 34 | + |
| 35 | +- `utils.llm.model_registry.MODELS` contains canonical provider-callable base models. |
| 36 | +- `utils.llm.model_runs.MODEL_RUNS` contains exact benchmarkable model-plus-options runs. |
| 37 | + |
| 38 | +Benchmarks should choose from `MODEL_RUNS` by `model_run_key`; forecast files should store that exact key. |
| 39 | + |
| 40 | +When adding a base model: |
| 41 | + |
| 42 | +- Add provider/lab registry entries first only if the provider or lab is missing. |
| 43 | +- Look up the model in Models.dev. Prefer a `ModelsDevReference` when Models.dev |
| 44 | + has the provider/model entry. |
| 45 | +- In Models.dev source paths, `provider_id` is the folder under `providers/`, |
| 46 | + and `model_id` is the TOML filename stem under `models/`, for example |
| 47 | + `providers/anthropic/models/claude-opus-4-8.toml` maps to `anthropic` / |
| 48 | + `claude-opus-4-8`. |
| 49 | +- The checked-in Models.dev snapshot is not a catalog; it contains only |
| 50 | + registry-referenced models and only `id`, `name`, and `release_date`. |
| 51 | +- Use exact Models.dev `provider_id`/`model_id` values. If a reference is wrong, |
| 52 | + refreshing the snapshot should fail and suggest nearby Models.dev entries. |
| 53 | +- Use `manual_release_date` when the model is missing from Models.dev, when the |
| 54 | + Models.dev entry lacks a usable full release date, or for deliberate |
| 55 | + historical/manual entries. |
| 56 | +- Put the model in the provider-specific list in `utils/llm/model_registry.py` (`OPENAI_MODELS`, `TOGETHER_MODELS`, `ANTHROPIC_MODELS`, `XAI_MODELS`, or `GOOGLE_MODELS`). |
| 57 | +- Insert the model where `(release_date, model_key)` stays ascending within its |
| 58 | + provider-specific list. |
| 59 | +- Use `provider_model_id` for the exact string sent to the provider API. It may differ from `model_key`, especially for routed providers like Together. |
| 60 | +- Set `active=False` only when a provider route should remain in registry history |
| 61 | + but should be excluded from current live-callable benchmark runs. |
| 62 | +- Do not add duplicate `model_key`s. `MODELS = create_models_list(...)` validates uniqueness. |
| 63 | + |
| 64 | +After changing `ModelsDevReference` values, refresh the Models.dev snapshot from the utils repo: |
| 65 | +```bash |
| 66 | +python - <<'PY' |
| 67 | +from scripts.refresh_models_dev_metadata import write_models_dev_snapshot |
| 68 | +
|
| 69 | +write_models_dev_snapshot() |
| 70 | +PY |
| 71 | +``` |
| 72 | + |
| 73 | +When adding a model run: |
| 74 | + |
| 75 | +- Add it to `utils/llm/model_runs.py` with |
| 76 | + `_model_run(model_run_key=..., model_key=..., options=...)`. |
| 77 | +- Write `model_run_key` explicitly as the stable benchmark identifier. Do not |
| 78 | + rely on implicit generation from model/options. |
| 79 | +- Put every runtime call option in the `ModelRun` declaration; do not add hidden defaults elsewhere. |
| 80 | +- Use exact provider option names and values as they are passed to `get_response`. |
| 81 | +- If an option affects performance and should appear in filenames/forecast keys, add or update a naming rule in `NAME_COMPONENT_RULES`. |
| 82 | +- If an option is intentionally name-neutral, add it to `NAME_NEUTRAL_OPTION_PATHS`. |
| 83 | +- Unknown option paths should fail loudly rather than silently producing ambiguous model-run keys. |
| 84 | +- `build_model_run_key(...)` is a suggested-key helper for consistency checks and |
| 85 | + new naming rules; the declared `model_run_key` remains the durable identity. |
| 86 | +- Do not add duplicate `model_run_key`s. `MODEL_RUNS = create_model_runs_list(...)` validates uniqueness. |
| 87 | +- `MODEL_RUNS` is the historical registry. `ACTIVE_MODEL_RUNS` is derived from |
| 88 | + it by dropping runs whose base `Model` has `active=False`. |
| 89 | +- Add unit tests for new naming behavior, registry inclusion, and routed provider options when relevant. |
| 90 | + |
| 91 | +## Artificial Analysis Model Runs |
| 92 | + |
| 93 | +When adding an Artificial Analysis-backed model run: |
| 94 | + |
| 95 | +- Use the checked-in Artificial Analysis snapshot as the source for the stable AA model ID and displayed AA name. |
| 96 | +- Refresh the snapshot from the AA endpoint; do not hand-edit individual AA models into the JSON file. |
| 97 | +- The official AA API key is `API_KEY_ARTIFICIAL_ANALYSIS` in GCP Secret Manager. |
| 98 | +- Do not hard-code an AA display name in a `ModelRun`; set `artificial_analysis_id` and let the run read the display name from the snapshot. |
| 99 | +- Do not add an `artificial_analysis_model` flag. A non-null `artificial_analysis_id` is the marker that a run is AA-backed. |
| 100 | +- Add or update the canonical base `Model` only if the provider-callable model is missing from `utils.llm.model_registry`. |
| 101 | +- Add the callable model-plus-options declaration to |
| 102 | + `ARTIFICIAL_ANALYSIS_MODEL_RUN_DECLARATIONS` in |
| 103 | + `utils/llm/artificial_analysis_model_runs.py`. Every declaration there is |
| 104 | + automatically included in `utils.llm.model_runs.MODEL_RUNS`; do not add the |
| 105 | + same AA run manually to `MODEL_RUNS`. |
| 106 | +- Use the exact provider option names that are passed at runtime. Token suffixes in model-run keys must reflect the actual token cap option used for the call. |
| 107 | + |
| 108 | +Artificial Analysis token caps should be encoded in the run options this way: |
| 109 | + |
| 110 | +- Non-reasoning models: use `16_384` output tokens, adjusted downward if the model has a smaller context window or a lower maximum output-token cap. |
| 111 | +- Reasoning models: use the maximum output tokens allowed by the model creator for that reasoning configuration. |
| 112 | +- If the correct cap is not clear from provider/model documentation or the AA metadata, stop and confirm rather than guessing. |
| 113 | + |
| 114 | +After adding an AA model run: |
| 115 | + |
| 116 | +- Add or update unit tests that prove the AA ID resolves from the snapshot and that `display_name` matches the AA leaderboard name. |
| 117 | +- Add or update shared registry coverage tests for the new selectable model-run key. |
| 118 | +- Run the focused model-run and AA metadata tests, then run the full lint/test suite before committing. |
| 119 | + |
| 120 | +## Validation |
| 121 | + |
| 122 | +- Run `make lint` before committing. It runs `isort .`, `black .`, `flake8 .`, |
| 123 | + and `pydocstyle .`. |
| 124 | +- Run `make test` before committing code changes. Use `PYTEST_ARGS=...` for a |
| 125 | + focused test pass while iterating. |
| 126 | +- Run `make test-integration` or `make test-integration-parallel` only when the |
| 127 | + relevant provider/GCP credentials are available. |
| 128 | + |
| 129 | +## Live Model-Run Smoke Tests |
| 130 | + |
| 131 | +Integration tests that hit real LLM APIs require provider API keys. |
| 132 | + |
| 133 | +- `tests/conftest.py` loads `.env`, then `configure_api_keys(from_gcp=True)` when pytest is run with `--integration`. |
| 134 | +- `configure_api_keys(from_gcp=True)` reads provider keys from GCP Secret Manager using the secret names in `utils/helpers/constants.py`. |
| 135 | +- The standard LLM secret names are `API_KEY_OPENAI`, `API_KEY_ANTHROPIC`, `API_KEY_GEMINI`, `API_KEY_XAI`, and `API_KEY_TOGETHERAI`. |
| 136 | +- To test a specific shared model run, set `LLM_MODEL_RUN_KEYS` to one or more comma-separated `model_run_key`s and run `pytest --integration tests/integration/llm/test_model_runs.py`. |
| 137 | +- The model-run integration test calls `model_run.get_response`, so it uses the run's declared provider route, provider model ID, and options. |
| 138 | +- For a newly added model run, prefer running its exact smoke test before assuming the provider accepts the declared options. |
0 commit comments