Skip to content

eval: run the smoke subject through a LiteLLM proxy - #344

Merged
qu0b merged 6 commits into
masterfrom
qu0b/eval-litellm-gateway
Aug 21, 2026
Merged

eval: run the smoke subject through a LiteLLM proxy#344
qu0b merged 6 commits into
masterfrom
qu0b/eval-litellm-gateway

Conversation

@qu0b

@qu0b qu0b commented Aug 21, 2026

Copy link
Copy Markdown
Member

Why

Both ends of the eval were pinned to the opencode-go zen gateway, so when zen drops a model there is no second road. That is what has been happening: deepseek-v4-flash went opt-in provider-side, every smoke case returns 0 tokens and a provider error, and Eval Smoke has been red on master since 2026-08-06 — nothing to do with panda.

What

A LiteLLM proxy is OpenAI-compatible, so both ends can use one.

  • Judge--judge-model litellm/<model> grades through LITELLM_PROXY_URL with LITELLM_PROXY_API_KEY, the same way codex/<model> already selects the Responses API.
  • Subject--subject litellm/<model>:cli. opencode has no built-in entry for a private proxy, so the generated config declares one (@ai-sdk/openai-compatible plus the model under test); without that models map opencode cannot resolve the id.
  • CI — the smoke subject moves to litellm/starflinger-anthropic:cli. The judge stays on zen: its path never broke, and a Qwen judge over a Claude subject keeps the families apart, which is the property the judge choice is documented to need.

starflinger-openai was the other candidate. The proxy currently answers it with No fallback model group found for original model_group=starflinger-openai, so it is not an option today.

Credentials

LITELLM_PROXY_API_KEY (repo secret) and LITELLM_PROXY_URL (repo variable) are set. The key is scoped to starflinger-anthropic and capped at $25 / 30d.

Verified

  • 7 new tests; the eval suite is green (94 passed)
  • through the public host, the judge's exact request shape returns well-formed rubric JSON: {"pass": true, "score": 1, "reason": "ok"}
  • starflinger-anthropic answers through the scoped key
  • existing transports are covered by tests proving they are untouched: a bare model name still grades through zen, codex/ still through the Responses API, an opencode-go subject renders no provider block

Not verified locally: a full subject run through the proxy — opencode is not installed on this machine, so the provider block is covered by rendering tests. This PR's own Eval Smoke run is the end-to-end check, and it is the point of the change.

Both ends of the eval are pinned to the opencode-go zen gateway, so when zen
drops a model out from under us there is no second road. That is not
hypothetical: deepseek-v4-flash went opt-in and every smoke case has come back
empty since, which is why CI is red on master rather than on anything panda
changed.

A LiteLLM proxy is OpenAI-compatible, so both ends can use one. The judge takes
a litellm/<model> spec, the same way it already takes codex/<model>. The subject
needs more: opencode has no built-in entry for a private proxy, so declare it as
an openai-compatible provider with the model under test, or opencode cannot
resolve the id.

Nothing changes for existing runs: a bare model name still grades through zen,
codex/ still grades through the Responses API, and an opencode-go subject
declares no provider block.

Verified against a live proxy: the judge's exact request shape returns a
well-formed rubric JSON through the public host.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 5 (limit 80)
  • diff bytes: 679309 (limit 500000)

Reviewed @ 88ea7753
"Hope is not a strategy." — Google SRE

The zen pin is what is red, not panda: deepseek-v4-flash went opt-in
provider-side, so every smoke case comes back with no tokens and no answer.

Point the subject at starflinger-anthropic through the proxy, with a key
scoped to that one model and capped at $25/30d. The judge stays on zen — its
path never broke, and a Qwen judge over a Claude subject keeps the two
families apart, which is the property the judge choice is documented to need.

starflinger-openai would have been the other candidate; the proxy currently
answers it with "No fallback model group found", so it is not an option today.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 6 (limit 80)
  • diff bytes: 681668 (limit 500000)

Reviewed @ 16ad314d
"Hope is not a strategy." — Google SRE

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

🐼 Smoke eval — 51073d4: ✅ 9/9 pass

📊 Interactive report — tokens p50 109,137 · tokens/solve 211,390.

Reference points: qu0b/eval-litellm-gateway@16ad314 78% · qu0b/eval-litellm-gateway@3c1bfb2 100% · qu0b/eval-litellm-gateway@f20cbac 78%.

question result tokens tools
forky_node_coverage 109,137 9
tracoor_node_coverage 147,523 11
mainnet_block_arrival_p50 67,252 6
list_datasources 50,170 3
block_count_24h 150,009 12
missed_slots_24h 106,466 11
chartkit_default_arrival_distribution 887,879 19
storage_upload_session_scoped 287,265 18
evm_faucet_fund_throwaway_address 96,807 9
🔭 Langfuse traces (9 runs; ⚠️ = failed)

The report walks this branch's commits against the master baseline and the most recent release. A self-contained copy is in the run's eval-smoke-* artifact.

@qu0b qu0b changed the title eval: let the subject and judge ride a LiteLLM proxy eval: run the smoke subject through a LiteLLM proxy Aug 21, 2026
The new smoke case caught the failure it was written for: given "I need test
ETH for a throwaway address", the agent spent 18 tool calls, never found
evm.faucet, and invented an HTTP faucet API (POST /api/claim) with a
placeholder address.

The function was documented but nothing an agent scans first said the module
funds anything: the module description listed execution, tracing, submission
and assembly, and no example was named after funding. Say it in the
description, and add the two-line example that is the whole answer.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 8 (limit 80)
  • diff bytes: 683697 (limit 500000)

Reviewed @ 3c1bfb2e
"Hope is not a strategy." — Google SRE

Six agent sessions in flight meant six concurrent conversations through the
gateway, each one a long tool-using run — that is a lot of simultaneous load
to put on a shared proxy for a job whose point is a sanity check, and it makes
a rate limit or a budget cap look like an eval regression.

Run them sequentially instead. The smoke job's timeout goes to 60 minutes to
pay for it: nine runs took 5m32s at six in flight, and the slowest single run
is the floor when there is only one.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 11 (limit 80)
  • diff bytes: 686950 (limit 500000)

Reviewed @ 466c3553
"Hope is not a strategy." — Google SRE

eval-smoke moved to the proxy; the full-eval and release-qualification jobs
did not, so the next dispatch or release would have failed exactly the way
smoke did. release-eval pinned deepseek-v4-flash explicitly, eval inherited it
through the harness default.

Fix it at the layer that owns it — DEFAULT_AGENT_MODEL and DEFAULT_SUBJECTS
now name proxy models, so local runs and the harden loop stop reaching for a
model that answers with nothing — and give both jobs the proxy credentials.
The harden pair stays two families (Claude and MiniMax) so a harness change
still cannot pass by suiting one vendor, and the judge deliberately stays on
opencode-go: a separate gateway from the subjects, and the half of the eval
that never broke.

The CI key's scope now covers both subject models. The usage examples in the
README, the module docstring and the settings help all named the dead model
too.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 11 (limit 80)
  • diff bytes: 693427 (limit 500000)

Reviewed @ f20cbacf
"Hope is not a strategy." — Google SRE

Drop minimax as a subject, in the defaults, the tests and the README example,
and narrow the CI key back to the one model.

That leaves the harden loop with a single subject, which is a real loss: the
pair existed so a harness change had to help two vendors rather than suit one.
Worth restoring when a second non-Claude model is available — starflinger-openai
would be it, once the proxy stops answering it with "No fallback model group
found".

Also stop failing the smoke job on rubric misses. It exists to prove the
pipeline runs end to end, and it now goes red for the reasons that mean the
harness is broken — no tokens, provider errors, crashes — rather than when a
graded agent flubs one of nine questions at k=1. Two runs today both scored
78%, failing different cases each time, with clean transports underneath;
release-eval already draws this line with --min-pass 0.
@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Skipped automated review — PR is too large for a useful single-shot review.

  • changed files: 11 (limit 80)
  • diff bytes: 694007 (limit 500000)

Reviewed @ 51073d4f
"Hope is not a strategy." — Google SRE

@qu0b
qu0b merged commit 14d060c into master Aug 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant