aix.vision¶
Image-to-text (vision) interface for AIX.
The cross-modal counterpart to aix.image (which is text→image): given an
image, produce text — a caption, an answer to a question about it, or a
structured judgement. Like the rest of AIX it is a thin, provider-neutral facade
over LiteLLM’s multimodal completion (the same backend chat uses), so the
same call routes to any vision-capable provider (OpenAI, Anthropic, Gemini,
OpenRouter, …) by model id alone.
describe_image() is the primitive: image (URL / local path / bytes / PIL
image / data: URI) + a prompt → text. to_image_content() exposes the
multimodal content block builder so callers can assemble richer messages (e.g.
multiple images in one turn) and pass them straight to aix.chat().
Examples
Caption an image (any vision-capable model):
>>> from aix.vision import describe_image
>>> describe_image("https://example.com/cat.jpg")
'A grey tabby cat sitting on a windowsill in afternoon light.'
Ask a specific question:
>>> describe_image("photo.png", prompt="What colour is the car?")
'The car is red.'
Build a multi-image message yourself and hand it to chat:
>>> from aix import chat
>>> from aix.vision import to_image_content
>>> msg = [{"role": "user", "content": [
... {"type": "text", "text": "Which is brighter?"},
... to_image_content("a.jpg"), to_image_content("b.jpg"),
... ]}]
>>> chat(msg, model="gpt-4o")
'The second image is brighter.'
compare_images() builds on these primitives: it puts a candidate image
beside one or more reference images and asks a vision model, via a structured
JSON path, for an explainable per-aspect likeness verdict — the “explain the
drift” half of a reference supervisor (face / costume / setting / lighting /
props matched?). The numeric identity-cosine gate lives elsewhere (lookbook);
this layer is the explainable checklist on top of it.
>>> from aix.vision import compare_images
>>> verdict = compare_images("gen.png", "locked_ref.png")
>>> verdict.match, verdict["identity"].match
(True, True)
Module Attributes
Shipped-default vision model, kept for reference. |
|
Default instruction when the caller doesn't supply one. |
|
Default rubric for |
|
the locked face, the architecture/set, the lighting, and the props. |
Functions
|
Describe (or answer a question about) |
|
Build a multimodal |
|
Compare a |
Classes
|
A vision model's verdict on a single rubric aspect. |
|
Structured result of comparing a candidate image to reference(s). |
- aix.vision.DFLT_COMPARE_RUBRIC = ('identity', 'costume', 'setting', 'lighting', 'props')¶
Default rubric for
compare_images()— a generic likeness checklist. Each entry is one aspect the vision model judges independently.
- aix.vision.DFLT_FILM_RUBRIC = ('face_identity', 'costume', 'setting_architecture', 'lighting', 'props', 'skin_realism')¶
the locked face, the architecture/set, the lighting, and the props. Pass it as
rubric=when comparing a generated frame against a locked reference.- Type:
Filmmaking-oriented rubric (Noel’s reference-supervisor checklist)
- aix.vision.DFLT_VISION_MODEL = 'gpt-4o-mini'¶
Shipped-default vision model, kept for reference. The active default is resolved from
aix.configat call time (seeaix.config.VisionConfig).
- aix.vision.DFLT_VISION_PROMPT = 'Describe this image in detail.'¶
Default instruction when the caller doesn’t supply one.
- class aix.vision.ImageComparison(match, confidence, explanation, aspects=<factory>, model=None)[source]¶
Bases:
objectStructured result of comparing a candidate image to reference(s).
Behaves like an ordered, read-only mapping of
aspect -> RubricVerdict(comparison["identity"],in, iteration,len) so per-aspect lookups read naturally, while also carrying the overall verdict.- match¶
Overall pass/fail across the whole rubric.
- confidence¶
Overall confidence in
[0.0, 1.0].
- explanation¶
A short overall summary of the comparison.
- aspects¶
The per-aspect verdicts, one
RubricVerdictper rubric item, in rubric order.
- model¶
The vision model id that produced the verdict.
- class aix.vision.RubricVerdict(aspect, match, confidence, note='')[source]¶
Bases:
objectA vision model’s verdict on a single rubric aspect.
- aspect¶
The rubric item this verdict is about (e.g.
"identity").
- match¶
Whether the candidate matches the reference for this aspect.
- confidence¶
The model’s self-reported confidence in
[0.0, 1.0].
- note¶
A short free-text explanation of the verdict.
- aix.vision.compare_images(candidate, reference, *, rubric=('identity', 'costume', 'setting', 'lighting', 'props'), model=None, api_key=None, max_tokens=None, temperature=0.0, detail=None, instruction='You are a strict visual continuity supervisor. The FIRST image is the CANDIDATE; the remaining image(s) are the locked REFERENCE the candidate must match. Judge each rubric aspect INDEPENDENTLY (do not let one aspect color another). For each aspect decide whether the candidate matches the reference, give a confidence in [0.0, 1.0], and a short note explaining what matches or drifts. Then give an overall match (true only if every important aspect matches), an overall confidence, and a one-sentence explanation.', **kwargs)[source]¶
Compare a
candidateimage toreferenceimage(s) on a rubric.The explainable half of a reference supervisor: a vision model returns a per-aspect pass/fail checklist (does the face match? the costume? the set? the lighting? the props?) plus an overall verdict — the explainable layer over a cheap numeric identity-cosine gate (which lives elsewhere, e.g. lookbook). Built on
to_image_content()(multi-image content block) and the same multimodalcompletionpath asdescribe_image(), asked via a JSON contract for a structured answer.The comparison is pointwise (each aspect judged on its own), not a ranked pairwise comparison, to avoid position bias.
- Parameters:
candidate (
Union[str,Path,bytes,Any]) – The image under review (URL / path / bytes / PIL image /data:URI — anythingto_image_content()accepts).reference (
Union[str,Path,bytes,Any,Sequence[Any]]) – The locked reference — a single image or a sequence of images (a locked set) in the same flexible formats. An empty sequence is an error.rubric (
Sequence[str]) – The aspects to evaluate, one verdict per item. Defaults toDFLT_COMPARE_RUBRIC; passDFLT_FILM_RUBRIC(or any custom sequence) to override — e.g.("face", "architecture", "props", "lighting"). Must be non-empty.model (
str|None) – Vision-capable model id or alias.None→ the configured default (aix.config.VisionConfig).api_key (
str|None) – Explicit API key;Noneresolves it for the model’s provider from the environment /.env/ config store.max_tokens (
int|None) – Cap on generated tokens (None→ provider default).temperature (
float|None) – Sampling temperature (default0.0for a stable, reproducible verdict;None→ provider default).detail (
str|None) – Image detail hint ("low"|"high"|"auto"), applied to every image block.instruction (
str) – The system-style framing prepended to the rubric. Has a sensible default; override to retune the supervisor’s strictness.**kwargs (
Any) – Extra provider-specific params forwarded to LiteLLM.
- Return type:
- Returns:
An
ImageComparison— overallmatch/confidence/explanationplus an ordered, mapping-like collection ofRubricVerdict(one per rubric aspect, keyed by aspect).- Raises:
ImportError – If LiteLLM is not installed.
ValueError – If
rubricis empty orreferenceis an empty sequence, or if the model’s reply can’t be parsed as the expected JSON verdict.
Examples
Default rubric, single reference:
>>> compare_images("gen.png", "ref.png") ImageComparison(match=True, confidence=0.9, ...)
Filmmaking rubric, a locked reference set:
>>> from aix.vision import DFLT_FILM_RUBRIC >>> compare_images( ... candidate="frame_042.png", ... reference=["ref_front.png", "ref_side.png"], ... rubric=DFLT_FILM_RUBRIC, ... )["face_identity"].match True
- aix.vision.describe_image(image, *, prompt='Describe this image in detail.', model=None, api_key=None, max_tokens=None, temperature=None, detail=None, **kwargs)[source]¶
Describe (or answer a question about)
imageand return the text.The image→text primitive.
imageaccepts a URL, a local path, raw bytes, a PIL image, or adata:URI (seeto_image_content()).promptis the instruction (default: a generic “describe this image”); pass a question for VQA or a rubric for a judgement. Everything pastimageis keyword.- Parameters:
image (
Union[str,Path,bytes,Any]) – The image (URL / path / bytes / PIL image /data:URI).prompt (
str) – The text instruction accompanying the image.model (
str|None) – Vision-capable model id (e.g.gpt-4o,claude-sonnet-4-6,gemini/gemini-1.5-pro) or an alias.None→ the configured default (aix.config.VisionConfig).api_key (
str|None) – Explicit API key;Noneresolves it from the environment /.env/ config store for the model’s provider.max_tokens (
int|None) – Cap on generated tokens (None→ provider default).temperature (
float|None) – Sampling temperature (None→ provider default).detail (
str|None) – Image detail hint ("low"|"high"|"auto").**kwargs (
Any) – Extra provider-specific params forwarded to LiteLLM.
- Return type:
- Returns:
The model’s text response.
- Raises:
ImportError – If LiteLLM is not installed.
>>> describe_image("cat.jpg", prompt="Caption it.") 'A cat on a sofa.'
- aix.vision.to_image_content(image, *, detail=None)[source]¶
Build a multimodal
image_urlcontent block forimage.imagemay be:an
http(s)://URL or adata:URI — passed through verbatim;a local file path (
strorPath) — read and inlined as a base64data:URI with a guessed MIME type;raw
bytes— base64-inlined (MIME sniffed from magic bytes, else JPEG);a PIL
Image— encoded to PNG and inlined.
detail("low"|"high"|"auto") is forwarded when set; the block is the OpenAI/LiteLLM multimodal shape understood across providers.>>> to_image_content("https://x/y.jpg") {'type': 'image_url', 'image_url': {'url': 'https://x/y.jpg'}} >>> to_image_content("data:image/png;base64,AAAA")["image_url"]["url"][:10] 'data:image'
- Return type: