# Ask about images

> Send images with a request and ask about them as you ask about text, on a server started with an image engine.

Source: https://opendecisio.com/docs/images/

Ask about images as you ask about text: the same [questions](https://opendecisio.com/docs/glossary/#question), the same answers, with the images in the request. This script sends one photo as a data URL, to a server started for images:

 

```
import base64
import json
import urllib.request

with open("photo.jpg", "rb") as f:
    image = "data:image/jpeg;base64," + base64.b64encode(f.read()).decode()

body = {
    "state": "A photo of a delivered parcel.",
    "images": [image],
    "questions": {"damaged": {"type": "noul", "instructions": "Is the parcel visibly damaged?"}},
}
request = urllib.request.Request(
    "http://127.0.0.1:8000/v1/systemone",
    data=json.dumps(body).encode(),
    headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request) as response:
    print("route:", response.headers["x-decisio-route"])
    print("damaged:", json.load(response)["answers"]["damaged"]["noul"])
```

 

A shape to fill in, not a command to run.

 

It prints `route: image` when the image engine answered, and the [probability](https://opendecisio.com/docs/glossary/#probability) that the parcel is damaged.

 

## 1 Start a server for images

 

Use the Qwen base: the image route was measured with it only. `--image-model` adds an image engine on the same card, for the requests that carry images:

 

```
pip install "decisio[serve]==0.19.0"
python -m decisio.serve.vllm_engine --base qwen3.6-35b-a3b --image-model Qwen/Qwen3.6-35B-A3B-FP8
```

 

Shown, not run: it needs Linux with one NVIDIA card, which this check does not have.

 

- The two engines’ default shares of the card, 0.47 for the text engine and 0.49 for the image engine, fit one card together, so no memory flag is needed.
- `--one-engine` loads only the image engine and serves text on it too, for a card that cannot hold both.
- With an image engine, the longest text stays at 32,768 tokens.
- A Mac does not serve images.

 

## 2 Send the images

  

| Limit | What it is |
| --- | --- |
| Images per request | as many as the context holds, up to the image engine’s `--max-images` (128 unless set); each costs tokens |
| Formats | PNG, JPEG or WebP |
| Size | up to 20 MB and 20 megapixels each; a larger one is refused with 422 |
| How | data URLs in `images`, `data:image/...` URIs inside the text, or a `multipart/form-data` request |

 

- A multipart request needs an `X-Decisio-Client` header, any value; without one it is refused with 415.
- `x-decisio-route: image` or `text` chooses the route explicitly; the answer’s `x-decisio-route` header says which served it.

 

## 3 Know what an image costs

 

The image is resized, keeping its proportions, and costs one token for every 32 by 32 pixels: between 64 and 16,384 tokens. A 1,024 by 768 image costs 768 tokens, and a 1,920 by 1,080 one 2,040. They count in `usage.input_tokens` and against the 32,768-token length.

 

## 4 Know what it does not do

 

- A request with images carries no certificate.
- A taught [task](https://opendecisio.com/docs/glossary/#task)’s examples are text only; an [abstention](https://opendecisio.com/docs/glossary/#abstain) [threshold](https://opendecisio.com/docs/glossary/#threshold)’s examples may carry images.

 

The image route’s scores, on the Qwen base, are in [the evaluation card](https://opendecisio.com/docs/evaluation-card/).

 

## What next

 

- [Server flags](https://opendecisio.com/docs/flags/): every flag of the image engine.
- [The HTTP API](https://opendecisio.com/docs/api/): the images field, the multipart form and the System One `assets` field.
- [Requirements and limits](https://opendecisio.com/docs/limits/): what was measured on what.
