mirror of
https://github.com/mudler/LocalAI.git
synced 2026-06-18 21:58:58 -04:00
feat(pii): NER tier engine — privacy-filter.cpp backend + NER-centric PII filter (#10360)
Squashed feat/pii-ner-tier-engine rebased onto master (was 45 commits; see backup/pii-ner-tier-engine-prerebase). Net change: - privacy-filter.cpp: standalone GGML engine for the openai-privacy-filter PII/NER token classifier, wired as a LocalAI gRPC backend (CPU/CUDA/Vulkan). TokenClassify moves off the patched llama.cpp path onto this backend. - PII filter reworked to be NER-centric (encoder/NER detection tier scanning whole conversations as one document), with a recreated bounded restricted- regex secret-matching pattern detector tier alongside it (per-model pii_detection.builtins / .patterns + core/services/routing/piipattern). - Detection labelled by source (ner vs pattern); backend trace / confidence / debug observability; analyze/redact exposed as a synchronous API. - Instance-wide default detector policy + per-usecase default-on; request filtering extended to completions, embeddings, edits & Ollama. - React UI: NER-centric PII editor, detector-models table, pattern/builtins editor, middleware default-policy UI. - Gallery: privacy-filter-multilingual token-classify model + NER install filter; token_classify known_usecase; batch sized to context for NER models. privacy-filter backend registered in the backend gallery (cpu/vulkan/cuda-13 meta + image entries with a capabilities map) matching its CI matrix jobs, and an /import-model auto-detect importer (PrivacyFilterImporter, narrow privacy-filter GGUF detection) replacing the prior pref-only registration. Reconciled against master's independent evolution: - Dropped master's PIIPatternOverrides feature (global-pattern runtime overrides + /api/pii/patterns API + runtime_settings.json persistence). The per-model NER + pattern-detector design supersedes it; it was built on the global redactor pattern set this branch replaced. - Reverted the llama.cpp Score carry-patch (0006-server-task-type-score): removed the patch and restored master's grpc-server.cpp Score RPC (direct llama_decode, slot-loop bypass) and LLAMA_VERSION pin, plus master's model_config validation forbidding score + chat/completion/embeddings on llama-cpp. token_classify is unaffected (it runs on the privacy-filter backend, not llama-cpp). Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Richard Palethorpe <io@richiejp.com>
This commit is contained in:
committed by
GitHub
parent
c133ca39dc
commit
3fa7b2955c
74
core/schema/pii.go
Normal file
74
core/schema/pii.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package schema
|
||||
|
||||
// PIIAnalyzeRequest is the body for POST /api/pii/analyze and
|
||||
// POST /api/pii/redact. The two endpoints share a request shape; only the
|
||||
// response differs (analyze never mutates text, redact applies policy).
|
||||
//
|
||||
// Detector selection is one of two ways:
|
||||
// - Detectors: explicit detector-model names (the primary path).
|
||||
// - Model: a consuming model name whose effective PII policy is used when
|
||||
// Detectors is empty — "what would this model do with this text?". The
|
||||
// policy resolves exactly as for the inline middleware: the model's own
|
||||
// pii.detectors, else the instance-wide pii_default_detectors, and
|
||||
// nothing when the model has PII disabled.
|
||||
//
|
||||
// One of the two must resolve to at least one detector, else the call is a
|
||||
// 400 — including a PII-enabled model with no detectors anywhere: the
|
||||
// middleware would scan nothing, and saying so loudly beats implying a clean
|
||||
// scan. The detection policy (mask/block/allow per entity group, min score)
|
||||
// lives on each detector model's own pii_detection block, exactly as for the
|
||||
// inline chat middleware.
|
||||
type PIIAnalyzeRequest struct {
|
||||
// Text is the string to scan. Bounded only by the server's global HTTP
|
||||
// body limit.
|
||||
Text string `json:"text"`
|
||||
// Detectors names the detector models to run (NER and/or pattern). Takes
|
||||
// precedence over Model.
|
||||
Detectors []string `json:"detectors,omitempty"`
|
||||
// Model is a consuming model whose effective PII policy (own
|
||||
// pii.detectors, else the instance default detectors; PII must be
|
||||
// enabled) is used when Detectors is empty.
|
||||
Model string `json:"model,omitempty"`
|
||||
// Reveal includes the per-entity hash_prefix in the response. Honoured
|
||||
// only for admin callers; ignored otherwise. The raw matched value is
|
||||
// never returned regardless.
|
||||
Reveal bool `json:"reveal,omitempty"`
|
||||
}
|
||||
|
||||
// PIIEntity is one detected span. EntityType is the detector group (e.g.
|
||||
// "EMAIL", "ANTHROPIC_KEY"); Source is the detector tier that produced it
|
||||
// ("ner" or "pattern"). Start/End are half-open byte offsets into the request
|
||||
// Text. Action is the policy action that fired after the overlap merge
|
||||
// (mask | block | allow). HashPrefix is present only for admin + reveal.
|
||||
type PIIEntity struct {
|
||||
EntityType string `json:"entity_type"`
|
||||
Source string `json:"source"`
|
||||
Start int `json:"start"`
|
||||
End int `json:"end"`
|
||||
Score float32 `json:"score"`
|
||||
Action string `json:"action"`
|
||||
HashPrefix string `json:"hash_prefix,omitempty"`
|
||||
}
|
||||
|
||||
// PIIAnalyzeResponse is returned by POST /api/pii/analyze (always 200). It
|
||||
// reports detections without mutating the text. Blocked is true when at
|
||||
// least one entity's action is block — i.e. the redact endpoint would reject
|
||||
// this text.
|
||||
type PIIAnalyzeResponse struct {
|
||||
Entities []PIIEntity `json:"entities"`
|
||||
Blocked bool `json:"blocked"`
|
||||
CorrelationID string `json:"correlation_id,omitempty"`
|
||||
}
|
||||
|
||||
// PIIRedactResponse is returned by POST /api/pii/redact when nothing blocks
|
||||
// (200). RedactedText is the input with masked spans replaced; Masked is true
|
||||
// when at least one span was replaced. When a block action fires the endpoint
|
||||
// returns 400 instead (with an error of type "pii_blocked" and the offending
|
||||
// entities), never a redacted body.
|
||||
type PIIRedactResponse struct {
|
||||
RedactedText string `json:"redacted_text"`
|
||||
Entities []PIIEntity `json:"entities"`
|
||||
Blocked bool `json:"blocked"`
|
||||
Masked bool `json:"masked"`
|
||||
CorrelationID string `json:"correlation_id,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user