illustration.inspection
Candidate inspection — classical-CV pre-filters + VLM caption/judge (R2 §2-3).
Two cost tiers, cheapest first:
Classical-CV pre-filters (R2 §3) — sub-10ms/image checks (aspect ratio, minimum size, brightness, blur, NSFW) that drop unusable candidates before any VLM token is spent. This is the single biggest cost lever in the loop. License-safe libraries only: Pillow (MIT-CMU) + NumPy for the core checks; the NSFW gate defaults to the Apache-2.0
Falconsai/nsfw_image_detectionViT (the torch stack the reranker already uses) and is fully injectable.VLM inspect (R2 §2) — a cheap one-sentence caption for the Correct path, or a full pointwise rubric judgement for the Ambiguous path. Both go through the injectable
describeseam, which defaults toaix.describe_image()(lazy import). Judgements are pointwise (one image at a time) rather than pairwise, mitigating the position bias that plagues comparative VLM judges (R2 §4); use a judge model from a different family than any generator to cut self-preference bias.
Every expensive step is an injectable seam, so the whole module is testable
offline with stubs (synthetic PIL images for the CV checks, canned strings for
describe) — no network, no paid API.
>>> # offline: a metadata-only check needs no image fetch
>>> from illustration.schema import ImageResult
>>> r = ImageResult(provider="p", id="1", url="u", width=1200, height=800)
>>> out = aspect_ratio_check()(r, lambda: None)
>>> out.name, out.passed
('aspect_ratio', True)
- illustration.inspection.CORE_CHECKS: tuple = (<function aspect_ratio_check.<locals>.check>, <function min_dimension_check.<locals>.check>, <function brightness_check.<locals>.check>, <function blur_check.<locals>.check>)
Core checks — need only Pillow + NumPy (the
[curate]extra), no model.
- illustration.inspection.Check
A check maps (result, get_image) -> CheckOutcome.
get_imageis a 0-arg thunk returning the candidate’s PIL image (cached) orNoneif unfetchable; metadata-only checks ignore it (so a metadata fail never triggers a fetch).alias of
Callable[[ImageResult,Callable[[], Any]],CheckOutcome]
- class illustration.inspection.CheckOutcome(name: str, passed: bool, value: float | None = None, reason: str | None = None)[source]
The result of one check on one candidate.
- illustration.inspection.DEFAULT_CHECKS: tuple = (<function aspect_ratio_check.<locals>.check>, <function min_dimension_check.<locals>.check>, <function brightness_check.<locals>.check>, <function blur_check.<locals>.check>, <function nsfw_check.<locals>.check>)
core CV + the NSFW gate. The NSFW check needs the classifier deps (
[rerank]extra); seedefault_checks()for the dependency-aware default actually used whenchecksis omitted.- Type:
The recommended set
- illustration.inspection.DFLT_CAPTION_MAX_TOKENS = 80
Token caps for the default VLM seam — a soft cost bound on the paid path. A one-sentence caption and a compact JSON rubric both need very few tokens.
- illustration.inspection.Describe
A describe seam maps (image_ref, prompt) -> text.
image_refis anythingaix.describe_image()accepts (URL / path / bytes / PIL / data URI).alias of
Callable[[Any,str],str]
- class illustration.inspection.InspectReport(*, provider: str, id: str, mode: str, caption: str | None = None, rubric: RubricScore | None = None, rationale: str | None = None)[source]
A VLM inspection of one candidate (caption or judge mode; R2 INSPECT).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class illustration.inspection.PrefilterReport(*, provider: str, id: str, passed: bool, reasons: list[str] = <factory>, values: dict[str, float]=<factory>)[source]
Per-candidate pre-filter verdict (the R2 PREFILTER stage record).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class illustration.inspection.PrefilterResult(passed: list[ImageResult], reports: list[PrefilterReport])[source]
The outcome of pre-filtering a candidate set.
- property dropped: list[PrefilterReport]
Reports for the candidates that failed at least one check.
- class illustration.inspection.RubricScore(*, subject: float = 0.0, action: float = 0.0, setting: float = 0.0, mood: float = 0.0, style: float = 0.0, quality: float = 0.0, overall: float = 0.0, rationale: str = '', parsed: bool = True)[source]
A pointwise VLM judgement of one candidate (R2 §4 rubric dimensions).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- recompute_overall() RubricScore[source]
Set
overallto the mean of the six rubric dimensions.
- exception illustration.inspection.SafetyGateDisabledWarning[source]
Raised when the default pre-filter set runs without the NSFW safety gate.
- illustration.inspection.aspect_ratio_check(*, min_ratio: float = 0.2, max_ratio: float = 5.0) Callable[[ImageResult, Callable[[], Any]], CheckOutcome][source]
Reject degenerate aspect ratios (extreme slivers/panoramas). Metadata-only.
Uses the result’s
width/height; passes when either is missing (can’t assess).ratio = width / height.
- illustration.inspection.blur_check(*, min_variance: float = 100.0) Callable[[ImageResult, Callable[[], Any]], CheckOutcome][source]
Reject blurry images via variance of the Laplacian (R2 §3; OpenCV-free).
The 3x3 Laplacian is applied with NumPy (no OpenCV) on the grayscale image; a low response variance means few sharp edges, i.e. blur.
- illustration.inspection.brightness_check(*, min_brightness: float = 0.1, max_brightness: float = 0.95) Callable[[ImageResult, Callable[[], Any]], CheckOutcome][source]
Reject near-black / blown-out images. Mean luminance, normalized to [0, 1].
- illustration.inspection.default_checks() tuple[source]
The default check set, chosen by what’s installed.
Returns
DEFAULT_CHECKS(core + NSFW) when the NSFW classifier deps are importable, elseCORE_CHECKS— and emits a :class:`SafetyGateDisabledWarning` so the absence of the safety screen is never silent (installillustration[rerank]to enable it). Passingchecks=toprefilter()explicitly always overrides this.
- illustration.inspection.inspect_candidate(query: str, result: ImageResult, *, mode: str = 'caption', describe: Callable[[Any, str], str] | None = None, model: str | None = None, max_tokens: int | None = None) InspectReport[source]
Inspect one candidate: a cheap caption (default) or a full rubric judge.
mode="caption"(the Correct-grade path) produces a one-sentence caption from the thumbnail;mode="judge"(the Ambiguous path) delegates tojudge_candidate().describedefaults to a lazyaix.describe_image()bound tomodeland capped atmax_tokens(defaultDFLT_CAPTION_MAX_TOKENS).
- illustration.inspection.judge_candidate(query: str, result: ImageResult, *, describe: Callable[[Any, str], str] | None = None, model: str | None = None, max_tokens: int | None = None) InspectReport[source]
Score one candidate against
querywith a pointwise VLM rubric.Uses the full-resolution image for accuracy.
describedefaults to a lazyaix.describe_image()capped atmax_tokens(defaultDFLT_JUDGE_MAX_TOKENS). The reply is parsed into aRubricScore(overall= mean of the six dimensions); an unparseable reply yields a neutral score flaggedparsed=Falseso the loop can treat it as ambiguous rather than wrongly accept or reject.
- illustration.inspection.min_dimension_check(*, min_width: int = 200, min_height: int = 200) Callable[[ImageResult, Callable[[], Any]], CheckOutcome][source]
Reject tiny images. Metadata-only (passes when dimensions are unknown).
- illustration.inspection.nsfw_check(*, max_prob: float = 0.5, classifier: Callable[[Any], float] | None = None) Callable[[ImageResult, Callable[[], Any]], CheckOutcome][source]
Hard-drop unsafe images (R2: NSFW is a non-negotiable drop).
classifierisimage -> nsfw_probability; it defaults to the Apache-2.0Falconsai/nsfw_image_detectionViT (torch/transformers — the[rerank]extra). Fails closed: a candidate whose image can’t be fetched or classified is dropped, never passed.
- illustration.inspection.prefilter(results: Sequence[ImageResult], *, checks: Sequence[Callable[[ImageResult, Callable[[], Any]], CheckOutcome]] | None = None, field: str = 'thumbnail_url', fetch: Callable | None = None) PrefilterResult[source]
Run
checksoverresults, keeping only candidates that pass all.Checks run cheapest-first and short-circuit on the first failure, so a candidate dropped on its (free) metadata never triggers an image fetch. Images are fetched at most once per URL (in-memory, for this call only);
fetchoverrides the fetch function (a test double avoids the network).checksdefaults todefault_checks()(core CV + NSFW where its deps are available).Returns a
PrefilterResultwith the survivingpassedresults and aPrefilterReportper input candidate.