docs: document aimlapi.com as a RULER judge provider - #1
Open
Lookoff-AIMLAPI wants to merge 2 commits into
Open
Conversation
added 2 commits
September 3, 2026 15:25
RULER already reaches AI/ML API today through the pinned LiteLLM's `aiml` provider, but nothing said so, and the two things a user gets wrong are not guessable from the code: the key is read from AIML_API_KEY (not the AIMLAPI_API_KEY spelling used elsewhere in that ecosystem), and judge cost metrics stay silently empty because token-count estimation in api_costs only covers the `openai` and `anthropic` provider prefixes. Both are failures that look like nothing happening rather than like an error, so they belong in docs rather than in a bug report. The accompanying unit test pins the route itself. AI/ML API support is entirely a property of the LiteLLM pin (`>=1.71.1,<=1.82.0`); if a future bump drops or renames the provider, the only symptom is a "LLM Provider NOT provided" failure deep inside a training run. Asserting the resolution at import time turns that into a fast, offline, keyless test failure instead.
Moves the aimlapi.com entry to the front of the hand-ordered Integrations navigation group and to the front of the judge-model examples in ruler.mdx. This is preferential placement in someone else's documentation and is not justified by anything technical, so it is isolated here to be dropped before any upstream proposal. The preceding commit stands on its own without it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ART has no provider registry, no provider enum and no per-provider subclass directory. Every judge call in RULER is delegated wholesale to LiteLLM (
src/art/rewards/ruler.py:236,await acompletion(model=judge_model, ...)), and_judge_provider(ruler.py:55-62) just splits the model string on the first/, so any LiteLLM provider prefix is accepted as-is.The pinned LiteLLM (
pyproject.toml:litellm>=1.71.1,<=1.82.0;uv.lockresolves 1.82.0) already ships a first-classaimlprovider. aimlapi.com therefore already works in ART today with zero code changes — this was verified with a real inference call, not by reading. So this PR ships documentation plus one route-guarding test, not a provider implementation. Forcing a provider abstraction into a repo that has none would be the wrong change.What changed
docs(ruler)commit — upstream-safe:docs/integrations/aimlapi.mdx(new) — setup, judge-model usage, model-id shape, base-URL override, and a working recipe for judge cost tracking.docs/fundamentals/ruler.mdx— one judge-model example and a<Note>pointing at the guide, in the existing "Judge Model" customization section.docs/docs.json— the new page registered in the Integrations navigation group, perAGENT.md:20-22andCONTRIBUTING.md:156-166.tests/unit/test_aimlapi_litellm_route.py(new, 5 tests) — assertsaimlis inlitellm.provider_listandlitellm.openai_compatible_providers, thataiml/<vendor>/<model>resolves tohttps://api.aimlapi.com/v1with the prefix stripped exactly once, that the key is read fromAIML_API_KEY, and that_judge_providerattributes it toaiml. Offline, keyless, no network.chore(aimlapi)commit — fork-only, drop before any upstream proposal:Why the two things documented are documented
Both are silent failures rather than errors, which is why they belong in prose:
The env var is
AIML_API_KEY, notAIMLAPI_API_KEY. LiteLLM chose the shorter spelling. A wrong name surfaces only as a 401 on the first judge call.Judge cost metrics are silently empty.
art/api_costs.py:311-323(_estimate_provider_cost) estimates cost from token counts only when the provider prefix is literallyopenaioranthropic; every other prefix returnsNoneand raises aValueErrorthatruler.py:84-86deliberately swallows. Judging works;costs/<context>/judge/rulernever appears.Note this is not aimlapi-specific —
groq/,together/,fireworks/,ollama/judges are all affected identically. It also meansregister_model_pricing()alone does not help, which is counter-intuitive: pricing resolves, then_estimate_provider_costdiscards it.register_cost_extractor("aiml", ...)is the route that works, and that is what the docs show. Both behaviours were confirmed live (see below). No change was made toapi_costs.py— widening it is a behaviour change to cost metrics for every non-OpenAI provider and should be a maintainer decision, not a side effect of a docs PR.Verification
Build/quality gate, per
CONTRIBUTING.md:18-26—uv run prek run --all-files:main)The 4
tydiagnostics are pre-existing and platform-related —os.sched_getaffinity,os.pidfd_open,os.pidfd_send_signalare Linux-only and this run was on macOS. Identical before and after; nothing here touches them.Unit tests —
uv run pytest --nbval --current-env --tb=short --continue-on-collection-errors tests/unit:The failing set is byte-identical before and after (diffed, not eyeballed). All 27 collection errors are
ModuleNotFoundErrorfortorch(22),transformers(2) andtinker(2) — those live in the CUDA-orientedbackend/megatron/tinkerextras thatuv sync --group devdoes not install on macOS. CI runs in the CUDA image and does not have this gap.Live inference call
One real call through ART's own documented public entry point —
art.rewards.ruler_score_group, on realart.Trajectoryobjects, no mocks, no raw curl:RULER's structured-output path (
response_format=Response, a Pydantic model) round-trips correctly, both trajectories were scored, ranking is correct, and rewards were written back onto the group.Additional live checks:
ruler()entry point, same result.MetricsBuilderand no extractor: judging succeeds,pending_by_scopeis{}— the cost metric is confirmed silently absent, and nothing crashes.register_model_pricing(...): still{}. Confirms the counter-intuitive behaviour described above.register_cost_extractor("aiml", ...):{'val': {'costs/val/judge/ruler': 0.00194375}}fromprompt=451 completion=138. The documented recipe is the one that was actually run.openai/gpt-5-5,anthropic/claude-sonnet-4.6,google/gemini-2.5-flash— all present, alltype == "openai/chat-completions".gpt-5-5andgemini-2.5-flashwere additionally driven live through theaiml/route.Tool calling was not exercised: RULER's judge call uses structured output and never sends
tools, so there is no tool-calling surface on this path to test.Scope notes
benchmarks/run.pyandsrc/art/mcp/generate_scenarios.pytake a user-suppliedbase_urland an OpenAI client, so they can be pointed at aimlapi.com, but they are generic and default to OpenRouter. Nothing aimlapi-specific was added there.embeddingmatches in the tree are neural-network weight embeddings in the Megatron/model-support code. Nothing on the embeddings endpoint can affect ART.