Skip to content

Commit 6bd97e2

Browse files
viraatcclaude
andcommitted
feat: auto-generate YAML config templates from schema, CLI bug fix
Bug fix: - CLI crash on --load-pattern + --target-qps (IndexError) — LoadPattern.type used alias= instead of name= on cyclopts.Parameter Template generation: - regenerate_templates.py generates minimal + full YAML templates from Pydantic schema field defaults (no hardcoded values) - Full templates include inline # comments auto-discovered from Field(description=) and Enum/Literal annotations - Minimal templates: required fields + placeholders only - Pre-commit hook auto-regenerates on schema changes; CI validates via CI env var detection (check-only mode) - init command uses model_dump(exclude_none=True) for offline/online/ concurrency; falls back to handwritten templates for eval/submission Schema improvements: - Added Field(description=) to all HTTPClientConfig, AccuracyConfig fields - New ScorerMethod enum (pass_at_1, string_match, rouge, code_bench_scorer, shopify_category_f1) for AccuracyConfig.eval_method Tests: - Hypothesis fuzz: 4000 random CLI flag combinations - Unit: all templates validate via from_yaml_file (auto-discovered glob) - Integration: generated templates run e2e against echo server - Init command: all 5 types tested Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c60b654 commit 6bd97e2

20 files changed

Lines changed: 1295 additions & 212 deletions

.github/workflows/test.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,44 @@ jobs:
5353
python -m pip install pip==26.0.1
5454
pip install -e ".[dev,test,performance]"
5555
pip-audit
56+
57+
schema-updated:
58+
runs-on: ubuntu-latest
59+
if: github.event_name == 'pull_request'
60+
steps:
61+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
62+
with:
63+
fetch-depth: 0
64+
65+
- name: Check for schema changes
66+
id: schema
67+
run: |
68+
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- \
69+
'src/inference_endpoint/config/schema.py' \
70+
'src/inference_endpoint/endpoint_client/config.py' \
71+
'src/inference_endpoint/commands/benchmark/cli.py' \
72+
'scripts/regenerate_templates.py' \
73+
'src/inference_endpoint/config/templates/*.yaml')
74+
echo "changed=$([[ -n "$CHANGED" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT"
75+
76+
- name: Set up Python 3.12
77+
if: steps.schema.outputs.changed == 'true'
78+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
79+
with:
80+
python-version: "3.12"
81+
82+
- name: Install dependencies
83+
if: steps.schema.outputs.changed == 'true'
84+
run: |
85+
python -m pip install --upgrade pip
86+
pip install -e ".[test]"
87+
88+
- name: Run schema fuzz tests
89+
if: steps.schema.outputs.changed == 'true'
90+
run: |
91+
pytest -xv -m schema_fuzz
92+
93+
- name: Check YAML templates are up to date
94+
if: steps.schema.outputs.changed == 'true'
95+
run: |
96+
python scripts/regenerate_templates.py --check

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ repos:
3535
hooks:
3636
- id: prettier
3737
types_or: [yaml, json, markdown]
38-
exclude: ^(src/inference_endpoint/openai/openai_types_gen.py|src/inference_endpoint/openai/openapi.yaml)$
38+
exclude: ^(src/inference_endpoint/openai/openai_types_gen.py|src/inference_endpoint/openai/openapi.yaml|src/inference_endpoint/config/templates/)
3939

4040
- repo: local
4141
hooks:
@@ -48,12 +48,12 @@ repos:
4848
args: ["--tb=short", "--strict-markers"]
4949
stages: [manual]
5050

51-
- id: validate-templates
52-
name: Validate YAML templates against schema
53-
entry: python -c "from pathlib import Path; from inference_endpoint.config.schema import BenchmarkConfig; [BenchmarkConfig.from_yaml_file(f) for f in sorted(Path('src/inference_endpoint/config/templates').glob('*.yaml'))]"
51+
- id: regenerate-templates
52+
name: Regenerate YAML templates from schema defaults
53+
entry: python scripts/regenerate_templates.py
5454
language: system
5555
pass_filenames: false
56-
files: ^src/inference_endpoint/config/(schema\.py|templates/)
56+
files: ^(src/inference_endpoint/config/(schema\.py|templates/.*)|src/inference_endpoint/endpoint_client/config\.py|scripts/regenerate_templates\.py)$
5757

5858
- id: add-license-header
5959
name: Add license headers

AGENTS.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ src/inference_endpoint/
162162
│ ├── ruleset_registry.py # Ruleset registry
163163
│ ├── user_config.py # UserConfig dataclass for ruleset user overrides
164164
│ ├── rulesets/mlcommons/ # MLCommons-specific rules, datasets, models
165-
│ └── templates/ # YAML config templates (offline, online, eval, etc.)
165+
│ └── templates/ # YAML config templates (_template.yaml minimal, _template_full.yaml all defaults)
166166
├── openai/ # OpenAI-compatible API types and adapters
167167
│ ├── types.py # OpenAI response types
168168
│ ├── openai_adapter.py # Request/response adapter
@@ -204,7 +204,16 @@ tests/
204204
- **License headers**: Required on all Python files (enforced by pre-commit hook `scripts/add_license_header.py`)
205205
- **Conventional commits**: `feat:`, `fix:`, `docs:`, `test:`, `chore:`
206206

207-
All of these hooks run automatically on commit: trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, debug-statements, `ruff` (lint + autofix), `ruff-format`, `mypy`, `prettier` (YAML/JSON/Markdown), license header enforcement.
207+
### Pre-commit Hooks
208+
209+
All of these run automatically on commit:
210+
211+
- trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, debug-statements
212+
- `ruff` (lint + autofix) and `ruff-format`
213+
- `mypy` type checking
214+
- `prettier` for YAML/JSON/Markdown
215+
- License header enforcement
216+
- `regenerate-templates`: auto-regenerates YAML config templates from schema defaults when `schema.py`, `config.py`, or `regenerate_templates.py` change
208217

209218
**Always run `pre-commit run --all-files` before committing.**
210219

docs/DEVELOPMENT.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,21 @@ pytest -s -v
273273
python -m pdb -m pytest test_file.py
274274
```
275275

276+
## YAML Config Templates
277+
278+
Config templates in `src/inference_endpoint/config/templates/` are auto-generated from schema defaults. When you change `config/schema.py`, regenerate them:
279+
280+
```bash
281+
python scripts/regenerate_templates.py
282+
```
283+
284+
The pre-commit hook auto-regenerates templates when `schema.py`, `config.py`, or `regenerate_templates.py` change. CI validates templates are up to date via `--check` mode.
285+
286+
Two variants are generated per mode (offline, online, concurrency):
287+
288+
- `_template.yaml` — minimal: only required fields + placeholders
289+
- `_template_full.yaml` — all fields with schema defaults + inline `# options:` comments
290+
276291
## Package Management
277292

278293
### Adding Dependencies

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ test = [
9797
"aiohttp==3.13.5",
9898
# Plotting for benchmark sweep mode
9999
"matplotlib==3.10.8",
100+
# Property-based testing (CLI fuzz)
101+
"hypothesis==6.151.10",
100102
]
101103
performance = [
102104
"pytest-benchmark==5.2.3",
@@ -184,6 +186,7 @@ markers = [
184186
"integration: marks tests as integration tests",
185187
"unit: marks tests as unit tests",
186188
"run_explicitly: mark test to only run explicitly",
189+
"schema_fuzz: hypothesis CLI fuzz tests (run in CI on schema changes)",
187190
]
188191
filterwarnings = [
189192
"ignore:Session timeout reached:RuntimeWarning",

0 commit comments

Comments
 (0)