AI Provider Selection

autociso uses AI to extract user lists from access screenshots and PDFs, classify assets and suppliers, and prefill ISO control evidence. Two providers are supported, selected per deployment via AI_VISION_PROVIDER:

  • Anthropic Claude (default). Image bytes are base64-encoded and sent directly to Claude’s /v1/messages API.
  • DeepSeek. Images are run through in-process OCR (tesseract) before any network call. The extracted text is masked for email PII, wrapped in a clearly-delimited UNTRUSTED IMAGE TEXT envelope, and sent as text only. Raw image bytes never leave your pod.

What changes per flow

FlowImage on the wire?Provider
Audit ingest (screenshot/PDF upload)Depends on AUDIT_REQUIRE_VISION. true (default): image goes to Anthropic. false: OCR text only.Anthropic when AUDIT_REQUIRE_VISION=true, otherwise the configured provider.
Asset extraction (uploaded image/PDF)Anthropic only — hard-coded.Anthropic.
ISO certificate extraction (PDF)Anthropic only — hard-coded.Anthropic.
Asset/supplier name + website analysisText-only.Whichever is configured.
AI chat (ai/chat SSE)Text-only.Whichever is configured.

AUDIT_REQUIRE_VISION=false turns off the default RequireVision for audit ingest. Asset and ISO image-bearing flows are NOT operator-tunable — they always route to Anthropic.

PII handling on the DeepSeek path

The DeepSeek provider OCRs the image with size/dimension/format guards (≤25 MiB, ≤8000×8000 pixels, ≤32 megapixels, PNG and JPEG only); normalises OCR-typical email corruption (alice@acme,comalice@acme.com); masks emails with deterministic per-call tokens; sends the masked text inside --- BEGIN UNTRUSTED IMAGE TEXT (filename) --- ... --- END UNTRUSTED IMAGE TEXT (filename) --- so the prompt-injection guard can identify it as data; and restores tokens in the response. Tokens never leave the provider’s goroutine.

Names and phone numbers are not masked in this phase — only email addresses.

Masking is deliberately invisible to the extraction result. The model is instructed that a [PII_xxxx] token is the value and must be copied into the output field verbatim, so a masked email survives the round trip and is restored before matching. Privacy costs nothing in accuracy here — but it does mean the model never sees a real address, so a prompt that ignores the tokens loses every email. If you supply a custom prompt for an asset (Prompt Override), the transcription rules covering tokens are always appended and cannot be opted out.

Extraction accuracy on the OCR path

When audit ingest runs on OCR text (AUDIT_REQUIRE_VISION=false), no model ever sees your screenshot — it reads what tesseract recovered. That text carries predictable damage, and it is worth knowing what to expect:

  • Characters are misread. Sergey Ilin is commonly recovered as Sergey lin (capital I read as lowercase l). The extraction prompt instructs the model to repair obvious character damage and keep the surname rather than drop it.
  • Layout is flattened. Sidebars, headers, and buttons interleave with table rows; badges next to a name (Owner, Admin) arrive as stray characters. The prompt describes the table shape so these are read as roles or ignored, not as names.
  • A damaged row is never “repaired” into a different person. The model is instructed that an empty field beats a plausible guess, and that a row must appear in the source to be reported.

The email is what carries a match. Employee matching treats an exact email as decisive, so a row whose name arrived damaged still attributes correctly as long as its email survived. Where the name is ambiguous and no email was recovered — a row reading only Sergey when two employees share that first name — autociso raises it for review rather than guessing. See Correct a misrecognised employee.

To remove OCR from the equation entirely, set AUDIT_REQUIRE_VISION=true and keep ANTHROPIC_API_KEY set: image-bearing audit calls then go to Anthropic and are read as pixels. This sends image bytes to Anthropic — a deliberate trade of the text-only guarantee for extraction accuracy.

When to choose DeepSeek

Use DeepSeek when:

  • Your tenant requires no image bytes leave the platform (text only).
  • You want lower cost on text-only flows (chat, name/website classification). Asset and ISO image-bearing flows continue to use Anthropic regardless; audit ingest follows AUDIT_REQUIRE_VISION.
  • Your DPA covers DeepSeek as a sub-processor. Update your RoPA accordingly.

When you switch to AI_VISION_PROVIDER=deepseek, leave ANTHROPIC_API_KEY set so per-call RequireVision=true flows continue to work via the Anthropic fallback. DEEPSEEK_BASE_URL defaults to https://api.deepseek.com/anthropic if unset; DEEPSEEK_MODEL defaults to deepseek-chat. Never set DEEPSEEK_MODEL to a Claude id — DeepSeek will return a vendor error.

Operator visibility

  • One startup log line records the active provider, fallback status, and OCR languages.
  • Audit failures on the DeepSeek+OCR path show [redacted — deepseek+OCR error path] in RawAIOutput (partial responses may contain unmasked PII fragments).
  • Boot in production refuses AI_VISION_PROVIDER=deepseek without an ANTHROPIC_API_KEY — that combination would silently lose audit-ingest accuracy.

What does NOT change

The console UI is identical regardless of provider; the stored audit data structure is identical (only RawAIOutput differs). PII tokenisation in your domSnapshot and text inputs continues to work as before, independent of the DeepSeek OCR-side masker.

Last reviewed: 2026-07-18

Was this page helpful?

Esc