Skip to content

latent.guardrails.scanners.llmguard

Classes

AnonymizeScanner

AnonymizeScanner(entity_types: list[str] | None = None, on_error: OnError = 'ignore')

Sanitizes PII in the prompt before it reaches the LLM (no blocking).

Returns passed=True with rewritten_input set to the anonymized prompt. The middleware forwards the redacted version to the model, but the caller's original messages list is not modified — it still holds the raw PII. Callers that persist or re-send messages after the stream must apply their own redaction if end-to-end PII erasure is required.

The underlying Anonymize scanner (which loads a transformer NER model plus the presidio recognizer registry) is cached at module scope, keyed by (entity_types, language), so it is constructed at most once per process per configuration. A fresh Vault is swapped in before each scan (under the entry's scan lock) to avoid cross-request PII retention.

BanTopicsScanner

BanTopicsScanner(topics: list[str] | None = None, threshold: float = 0.75, on_error: OnError = 'ignore')

GibberishScanner

GibberishScanner(threshold: float = 0.7, on_error: OnError = 'ignore')

MaliciousURLsScanner

MaliciousURLsScanner(threshold: float = 0.7, on_error: OnError = 'ignore')

PromptInjectionScanner

PromptInjectionScanner(threshold: float = 0.95, on_error: OnError = 'ignore')

SensitiveScanner

SensitiveScanner(entity_types: list[str] | None = None, on_error: OnError = 'ignore')

Detects and redacts sensitive output (passive — never blocks).

Returns passed=True with rewritten_output set to the redacted version. In streaming mode the original TextDelta events are already yielded before this scanner runs; the redacted text is surfaced via GuardrailViolation.output_text after the stream completes — use it for logging, auditing, or application-layer substitution.

The underlying Sensitive scanner (which loads a transformer NER model plus the presidio recognizer registry) is cached at module scope, keyed by (entity_types, redact), so it is constructed at most once per process per configuration. Sensitive.scan does not mutate scanner state, so no per-scan lock is taken.

ToxicityScanner

ToxicityScanner(threshold: float = 0.5, on_error: OnError = 'ignore')

Methods

AnonymizeScanner.scan

scan(prompt: str) -> ScanResult

SensitiveScanner.scan

scan(prompt: str, output: str) -> ScanResult