本文へ移動
Signalcraft
English

← Signalcraft一覧へ戻る

vLLMのStructured Outputs移行を入力形式から確認する

vLLMのStructured Outputs移行を入力形式から確認する

vLLMのOpenAI互換endpointでJSONを強制するとき、古い記事のguided_jsonをそのまま使うとversionによってrequestが拒否されます。

現在の公式資料を読むと、古いguided系fieldと、現在のstructured_outputs、OpenAI互換のresponse_formatを分けて移行する必要があります。

JSON Schemaを追加することと、抽出値の意味が正しいことを保証することも別です。

旧fieldの場所を検索する

以前のvLLMでは、requestの追加parameterへ次のようなguided_jsonを渡していました。

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

現行のStructured Outputs公式資料では、guided_json、guided_regex、guided_choice、guided_grammarなどをlegacy APIとして扱います。

まずrepository、client、prompt template、テストへ残る旧fieldを検索します。

利用中のvLLM versionが、旧fieldを受け付けるかも実際のserverで確認します。

structured_outputsへ移行する

guided_jsonに相当するJSON Schemaは、次のように書きます。

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

対応関係は次です。

旧field 現在の指定
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

OpenAI互換clientから送る場合は、通常extra_bodyへvLLM固有の指定を入れます。

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": "名前と年齢を抽出してください。"},
    ],
    extra_body={
        "structured_outputs": {
            "json": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                },
                "required": ["name", "age"],
            },
        },
    },
)

response_formatとの違いを確認する

JSON Schemaだけを使う場合は、OpenAI互換のresponse_formatへ指定する方法もあります。

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

response_formatでは、json_schemaの中へnameと実際のschemaを入れます。

structured_outputsはvLLMの制約指定であり、response_formatはOpenAI互換requestの形式です。

同じSchemaを表現できても、clientやハーネスがどちらを転送するかを確認します。

field名だけを置き換えず、requestの入れ子構造とレスポンスの取り出し方をテストします。

server起動時の設定を確認する

OpenAI互換serverでは、Structured Outputsは通常有効です。

backendを固定したい場合は、起動時にstructured-outputs-config.backendを指定します。

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

autoでは、requestと利用可能なbackendからvLLMが選択します。

backendの挙動とregex syntaxは、vLLM versionとbackendで変わり得ます。

再現性が必要なら、対応状況を確認して明示的なbackendを選びます。

Structured Outputsが保証しないこと

JSON Schemaは、出力を構文と構造へ合わせる制約です。

入力文へ値が実際に存在することや、業務上の意味が正しいことまでは保証しません。

ageをintegerとして生成できても、入力に書かれていない年齢を正しく推測できるとは限りません。

アプリ側で次の検証を分けます。

  • syntax validation: JSONとしてparseできるか確認する
  • schema validation: type、必須field、enumを確認する
  • semantic validation: 入力との対応、範囲、業務ruleを確認する
  • retry decision: 同じinputを再送するか、指示を変えるか決める

Structured Outputsは、semantic validationやretryを代行しません。

LLMの出力は検証前の入力として扱います。

reasoning modelと組み合わせる

reasoning modelでは、推論部分と最終回答を分離するためreasoning parserを使う場合があります。

vLLMの資料には、推論中のStructured Outputsを有効にするenable_in_reasoningがあります。

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

必要性はmodel、chat template、reasoning parser、vLLM versionで変わります。

JSONが崩れるときは、Schemaだけでなく4つの組み合わせを確認します。

移行チェックリスト

  1. vLLM versionを固定する
  2. guided_jsonなどの旧fieldを検索する
  3. structured_outputs.jsonまたはresponse_formatへ移す
  4. response_formatならnameとschemaの入れ子を確認する
  5. modelのchat templateを確認する
  6. 非reasoning modelで最小JSONを試す
  7. reasoning modelではparserとの組み合わせを試す
  8. syntax、schema、semanticの検証を分離する

移行の成功条件は、requestが受け付けられることだけではありません。

期待するSchema、意味検証、失敗時のretry境界まで再現できることを確認します。

参考資料