Skip to content
Signalcraft
日本語

← Back to Signalcraft

Migrating vLLM Structured Outputs from Legacy Guided Fields

Migrating vLLM Structured Outputs from Legacy Guided Fields

When forcing JSON through vLLM’s OpenAI-compatible endpoint, copying guided_json from an old article may be rejected by the installed version.

Current documentation separates legacy guided fields from structured_outputs and the OpenAI-compatible response_format.

Adding a JSON Schema is also different from guaranteeing that extracted values are semantically correct.

Find legacy fields first

Older vLLM examples passed a value such as this as an additional request parameter:

{
  "guided_json": {
    "type": "object",
    "properties": {
      "name": {"type": "string"},
      "age": {"type": "integer"}
    },
    "required": ["name", "age"]
  }
}

The current Structured Outputs documentation treats guided_json, guided_regex, guided_choice, and guided_grammar as legacy APIs.

Search the repository, client, prompt templates, and tests for legacy fields first.

Also verify whether the installed vLLM version still accepts them.

Migrate to structured_outputs

The JSON Schema equivalent of guided_json is:

{
  "structured_outputs": {
    "json": {
      "type": "object",
      "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"}
      },
      "required": ["name", "age"]
    }
  }
}

The mapping is:

Old field Current setting
guided_json structured_outputs.json
guided_regex structured_outputs.regex
guided_choice structured_outputs.choice
guided_grammar structured_outputs.grammar
guided_whitespace_pattern structured_outputs.whitespace_pattern
structural_tag structured_outputs.structural_tag

When using an OpenAI-compatible client, put the vLLM-specific value in extra_body in the usual configuration.

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="-",
)

completion = client.chat.completions.create(
    model="MODEL_ID",
    messages=[
        {"role": "user", "content": "Extract the name and age."},
    ],
    extra_body={
        "structured_outputs": {
            "json": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                },
                "required": ["name", "age"],
            },
        },
    },
)

Check response_format separately

For JSON Schema alone, the OpenAI-compatible response_format form is another option.

{
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "person",
      "schema": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "age": {"type": "integer"}
        },
        "required": ["name", "age"]
      }
    }
  }
}

The json_schema wrapper contains name and the actual schema.

structured_outputs is vLLM’s constraint format, while response_format is the OpenAI-compatible request format.

Even when they express the same Schema, check which one the client or harness forwards.

Test request nesting and response extraction rather than replacing only the field name.

Check server startup settings

Structured Outputs is normally enabled on the OpenAI-compatible server.

To choose a backend, specify structured-outputs-config.backend at startup.

vllm serve MODEL_ID \
  --structured-outputs-config.backend=auto

With auto, vLLM chooses from the request and available backends.

Backend behavior and regular-expression syntax vary by vLLM version and backend.

Choose an explicit backend after checking compatibility when reproducibility matters.

What Structured Outputs does not guarantee

A JSON Schema constrains output syntax and structure.

It does not guarantee that a value exists in the input or that its meaning is correct.

The model may produce an integer age without correctly inferring an age that is absent from the input.

Keep these application checks separate:

  • Syntax validation: can the response be parsed as JSON?
  • Schema validation: are types, required fields, and enum values correct?
  • Semantic validation: does the output match the input, ranges, and business rules?
  • Retry decision: should the same input be resent or instructions changed?

Structured Outputs does not perform semantic validation or retry decisions.

Treat LLM output as untrusted input until it has been validated.

Combine it with reasoning models

Reasoning models may use a reasoning parser to separate reasoning from the final answer.

vLLM documents enable_in_reasoning for enabling Structured Outputs during reasoning.

vllm serve MODEL_ID \
  --reasoning-parser MODEL_SPECIFIC_PARSER \
  --structured-outputs-config.enable_in_reasoning=True

Whether it is required depends on the model, chat template, reasoning parser, and vLLM version.

When JSON becomes malformed, inspect those four inputs together rather than changing only the Schema.

Migration checklist

  1. Pin the vLLM version
  2. Search for old fields such as guided_json
  3. Move to structured_outputs.json or response_format
  4. Check the name and schema nesting for response_format
  5. Confirm the model’s chat template
  6. Try minimal JSON with a non-reasoning model
  7. Test the reasoning-parser combination for reasoning models
  8. Keep syntax, schema, and semantic validation separate

Migration success is not only that the request is accepted.

Verify the expected Schema, semantic checks, and retry boundary as well.

References