Skip to content

OpenAI API: image input should have default "detail" field. - #2786

Open
kflu wants to merge 1 commit into
openai:mainfrom
kflu:patch-1
Open

kflu wants to merge 1 commit into
openai:mainfrom
kflu:patch-1

Conversation

@kflu

@kflu kflu commented Dec 16, 2025 •

Copy link
Copy Markdown

This is to be compatible with OpenAI API official document:

https://platform.openai.com/docs/api-reference/responses/create?lang=curl

curl https://api.openai.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4.1",
    "input": [
      {
        "role": "user",
        "content": [
          {"type": "input_text", "text": "what is in this image?"},
          {
            "type": "input_image",
            "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
          }
        ]
      }
    ]
  }'

where detail is NOT specified.

Deserializing the above JSON request would result in pydantic error without the fix.

  • I understand that this repository is auto-generated and my pull request may not be merged

Changes being requested

Additional context & links

This is to be compatible with OpenAI API official document:

https://platform.openai.com/docs/api-reference/responses/create?lang=curl

```
curl https://api.openai.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4.1",
    "input": [
      {
        "role": "user",
        "content": [
          {"type": "input_text", "text": "what is in this image?"},
          {
            "type": "input_image",
            "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
          }
        ]
      }
    ]
  }'
```

where `detail` is NOT specified.

Deserializing the above JSON request would result in pydantic error without the fix.
@kflu
kflu requested a review from a team as a code owner December 16, 2025 20:15
@jnohclee-rgb

Copy link
Copy Markdown

AI-assisted independent offline check at b9be6eaac63269b300555d1fe9c6e263b665f3d2, compared with pinned main 919b6236382f3f9f76d8453efb9f9ad03cff1126.

A 12-case observation matrix (image_url/file_id with omitted, null, low/high/auto and invalid detail values) distinguishes the annotation change from runtime defaults. Local TypeAdapter validation rejects omitted/null detail on pinned main and accepts both on this head; invalid literals remain rejected by the adapter. SDK maybe_transform preserves the supplied dictionary for every case on both sources: omitted detail stays absent, including on this head; explicit null stays null. The TypedDict class attribute detail="auto" is therefore not an injected client-side default.

If the intended fix is just optional key presence, total=False already supports a non-Required detail: Literal["low", "high", "auto"] without wrapping it in Optional or assigning a class value. Optional also widens the value annotation to None, which is a separate choice. Please separate those decisions in the change/tests so users do not infer runtime default injection.

Scope: Actual TypedDict annotations checked by Pydantic TypeAdapter, plus actual SDK maybe_transform. TypeAdapter is an independent local checker, not SDK runtime request validation; maybe_transform also preserves invalid values. No endpoint or assertion that the provider accepts/rejects null detail. No default-setting code added. Python 3.14.7 / Pydantic 2.13.5 and shared local dependencies; this is a bounded matrix, not a full SDK suite or historical dependency matrix. Network denied by the sandbox.

Standalone reproducer (run separately with each source tree on PYTHONPATH)
import json,pydantic
from openai.types.responses.response_input_image_param import ResponseInputImageParam
from openai._utils import maybe_transform
adapter=pydantic.TypeAdapter(ResponseInputImageParam);rows=[]
for source in ['image_url','file_id']:
 for label,field in [('omitted',{}),('null',{'detail':None}),('low',{'detail':'low'}),('high',{'detail':'high'}),('auto',{'detail':'auto'}),('invalid',{'detail':'invalid'})]:
  data={'type':'input_image',source:'fictional',**field};accepted=True;validated=None;error=None
  try:validated=adapter.validate_python(data)
  except pydantic.ValidationError:accepted=False;error='ValidationError'
  transformed=maybe_transform(data,ResponseInputImageParam)
  rows.append({'source':source,'case':label,'adapter_accepts':accepted,'validated':validated,'exception':error,'transformed':transformed,'transform_preserves_supplied_fields':transformed==data})
print(json.dumps({'cases':rows,'typed_dict_class_default':getattr(ResponseInputImageParam,'detail',None),'scope':'Local TypeAdapter annotation validation and SDK maybe_transform only; no Responses endpoint call or nullable-detail provider contract proof.'}))

This branch has not been deployed

No deployments
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.

2 participants