[Proposal] PRISM — 153-key Legitimacy Layer for vLLM-SR Model Selection
Issue: #1422
Author: Mossaab Souaissa — MSIA Systems
Milestone: v0.3 — Themis
Reference: https://doi.org/10.5281/zenodo.18750029
White Paper: https://github.com/user-attachments/files/25750911/PRISM-Vllm-SR-whitepaper-COMPLET-EN.pdf
1. Context & Motivation
vLLM-SR answers: which model is best suited for this request?
PRISM answers: is the selected model legitimate to respond to this specific query?
These are two different questions. They are complementary, not redundant.
The lying model problem
Without a structural constraint, any model can respond to any query — even outside its training domain. This produces confident hallucinations: the model improvises answers with high confidence in a domain it does not master.
The current vLLM-SR pipeline has no post-selection legitimacy verification. PRISM adds this layer without modifying existing routing logic.
Design principle: add without breaking
PRISM integrates as optional extensions of existing components:
- If
prism.enabledis absent from a model's config → existing behavior unchanged - If no
type: "prism-execution"plugin block in a decision → Key 3 skipped - If PRISM registry is not ready at request time → fallback to
"general"→ standard vLLM-SR routing
| PRISM component | Integration point | Type |
|---|---|---|
| Key 1 — QUALIFICATION | model_config in config.yaml | prism.enabled: true + auto-discovery at startup |
| Key 2 — CLASSIFICATION | req_filter_classification.go | New evaluation block — in-process candle-binding |
| Key 3 — EXECUTION | req_filter_prism_execution.go | New ExtProc filter — follows req_filter_jailbreak.go pattern |
| 153-Registry | pkg/registry/prism_registry.go | In-memory store, populated async at startup via Key 1 |
Scope of this PR: hybrid mode only (Key 1 + Key 2 + Key 3).
fine_filter and coarse_filter are documented in §9 as future variants.
2. Architecture Overview
HTTP Request
│
▼
ENVOY PROXY / API GATEWAY
│
▼
processor_req_body.go
│
├── PHASE 1 — Signal Extraction
│ runClassification() ← existing (keyword, embedding, domain...)
│ runPrismClassification() ← NEW Key 2
│ writes: ctx.PrismDomain · ctx.PrismConfidence · ctx.PrismKeywords
│ fallback: ctx.PrismDomain = "general" on any error or registry not ready
│
├── PHASE 2 — Decision Engine
│ evaluateDecisions() ← existing, unchanged
│ → candidates = modelRefs from matched decision
│
├── PHASE 3 — Model Selection (pre-filter + re-route loop)
│ filterCandidatesByPrism() ← NEW — filter candidates by PrismDomain
│ LOOP (max MaxRerouteAttempts+1):
│ selectModelFromCandidates() ← existing (Elo/AutoMix/MLP), unchanged
│
├── PHASE 4 — Plugin Execution (inside loop)
│ runSemanticCache() ← existing
│ runJailbreakFilter() ← existing
│ runPIIFilter() ← existing
│ runPrismExecution() ← NEW Key 3
│ guard: decision.GetPluginConfig("prism-execution") required
│ reads: ctx.PrismDomain · ctx.PrismConfidence · ctx.SelectedModel
│ writes: ctx.PrismRefused = true on failure
│ loop exits if ctx.PrismRefused == false
│ if all candidates refused → ctx.Blocked = true (HTTP response via buildResponse())
│
└── buildResponse() → ENVOY → CLIENT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STARTUP — once per server start (non-blocking)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NewOpenAIRouter(config)
→ NewPrismRegistry(config) — returns immediately
go qualifyAllModels() — runs in background goroutine
for each model with prism.enabled = true:
send Key 1 QUALIFICATION prompt → parse JSON → register in 153-Registry
registry.ready = true — PRISM activates for all subsequent requests
3. Key 1 — QUALIFICATION (async auto-discovery at startup)
3.1 Principle
The human operator declares only prism.enabled: true in model_config. Nothing else.
At startup, NewPrismRegistry() launches a background goroutine that sends the Key 1 QUALIFICATION prompt to each enabled model, parses its self-declaration, and registers it in the 153-Registry. The router starts immediately — PRISM activates once the goroutine completes.
During initialization: IsReady() returns false → runPrismClassification() sets ctx.PrismDomain = "general" → standard vLLM-SR routing without PRISM.