Skip to content

feat: conform /v1/decisions to the GA Decisions schema and align with vLLM's request fields - #17

Merged
planetf1 merged 2 commits into
mainfrom
feat/openai-ga-conformance-vllm-alignment
Oct 26, 2026
Merged

planetf1 merged 2 commits into
mainfrom
feat/openai-ga-conformance-vllm-alignment

Conversation

@planetf1

@planetf1 planetf1 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

OpenAI's Decisions API changed last week, and vLLM now ships its own decision endpoints. This brings /v1/decisions up to date with OpenAI's schema for text, and lets /v1/systemone accept the extra fields vLLM's endpoint has, so clients written for either work here as they are.

What you get

  • Bigger requests. Up to 400 questions per request (was 200), and input_json parts for passing structured data without turning it into a string. A question's instructions can also be text and JSON parts.
  • A private cache per tenant. cache_salt keeps one tenant's prefix cache apart from another's, so cache timing and cached_tokens can't reveal what someone else sent. It works on both routes.
  • A way to spot a bad setup. /v1/systemone responses now include label_mass for each question, which drops when the marker or layout is wrong. Before, it was only logged.
  • Fewer surprises for vLLM clients. /v1/systemone accepts chat_template_kwargs, joint, images, audio, videos, priority and request_id at their defaults, instead of answering 422.

What it doesn't do

The adapter reads one block of text and a question, so the prompt it sees is unchanged and these get a clear error instead of an answer:

  • developer, system and assistant messages, and tool calls and outputs (put what the questions are about in a user message)
  • images
  • request-level instructions on /v1/systemone
  • two choices that would merge into one

chat_template_kwargs is checked and never passed on, because the 8b chat template renders some of its keys without escaping. Only enable_thinking: false is accepted.

The README lists all of this.

How it was checked

  • The tests now run against the current OpenAI schema, with 3,000 requests generated from it and checked on the way in and out.
  • OpenAI's Python SDK reads the responses.
  • On a running server, the new vllm_fields check in scripts/e2e_check.py passes with the existing wire and probe checks, and a fresh cache_salt starts with an empty cache.

Not checked: the responses haven't been compared with OpenAI's live service, and VLLM_BATCH_INVARIANT=1 hasn't been tried with this plugin.

The first commit stands alone (the schema update). The second adds the vLLM fields and label_mass.

Re-pin the conformance tests to the general-availability revision of OpenAI's
Decisions schema (openai-openapi 8243cc8f, 2026-10-24) and make the route
accept what that revision allows and this adapter can serve:

- up to 400 questions per request on both routes (was 200)
- `input_json` parts in `input`, rendered as compact JSON the way an object
  `state` is on /v1/systemone
- a question's `instructions` as a string or text and JSON parts

Image parts, developer, system and assistant messages and tool-call items stay
unsupported and answer 400 in OpenAI's error shape; the README lists them under
"Deliberate exceptions on /v1/decisions", and the spec tests pin each one.
Translation errors for these now return 400 instead of escaping the handler.

scripts/probe_check.py now checks 400/401 questions, and e2e_check.py checks
that `input_json` and instruction parts answer like their plain equivalents.

Assisted-by: Claude Code
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…emone

vLLM now ships its own /v1/systemone and /v1/decisions. Follow its request and
response additions where they leave the prompt unchanged, so a client written for
vLLM works here, and say plainly what is not supported.

Accepted:
- /v1/systemone takes `cache_salt`, `chat_template_kwargs`, `joint`, the media
  fields, `priority` and `request_id`, at their defaults. `model` stays required.
  `chat_template_kwargs` is validated and dropped, never forwarded: the 8b chat
  template renders some of its keys unescaped, and the adapter name is always the
  server's. Only `enable_thinking: false` is allowed.
- `cache_salt` is validated with vLLM's rule and set on every engine read, so
  tenants can keep their prefix caches apart. /v1/decisions also takes it and
  `joint: false`, the two extensions vLLM adds on that route.
- /v1/systemone responses carry `diagnostics` per question (`label_mass`,
  `argmax_is_label`), as vLLM's do. /v1/decisions does not, because OpenAI's
  response schema forbids extra fields.

Refused, with a message that names the part and says what to do:
- developer, system and assistant messages and tool calls and outputs on
  /v1/decisions, and request-level `instructions` on /v1/systemone. Each would
  add text the adapter was not trained to read, so the prompt stays exactly as it
  was. Put what the questions are about in a user message.
- images, and two choices that would merge into one option.

`_answer_question` now returns a typed `QuestionDiagnostics` as a fourth element.
The README lists what is and is not supported, and tests/test_openai_spec.py pins
each unsupported request as a named case. scripts/e2e_check.py gains a
`vllm_fields` check, including that a `cache_salt` gets its own prefix cache.

Assisted-by: Claude Code
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
@planetf1
planetf1 force-pushed the feat/openai-ga-conformance-vllm-alignment branch from ed61fca to 5196bcc Compare October 26, 2026 19:55
@planetf1
planetf1 marked this pull request as ready for review October 26, 2026 20:02
@planetf1
planetf1 merged commit 529b4fe into main Oct 26, 2026
3 checks passed
@planetf1
planetf1 deleted the feat/openai-ga-conformance-vllm-alignment branch October 26, 2026 20:02
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