Skip to main content

Medical Verification Layer for Multimodal LLMs — composable, auditable guardrails for structured LLM outputs

Project description

VLM-Guard

Medical Verification Layer for Multimodal LLMs.

VLM-Guard is a framework for building rule-based verification layers that catch physically impossible, biologically inconsistent, or logically contradictory outputs from multimodal LLMs — before they reach the end user.

from vlm_guard import GuardrailEngine, BaseRule, RuleResult

# 1. Define a rule
class NoMalariaInTissueRule(BaseRule):
    name = "sample_type_check"
    description = "Malaria requires blood smear, not tissue biopsy"

    def condition(self, analysis, context):
        return (
            analysis.label == "Malaria"
            and "tissue" in context.get("sample_type", "").lower()
        )

    def action(self, analysis, context):
        analysis.label = "Unclear"
        analysis.confidence = "Low"
        return analysis, RuleResult(
            action_taken=True, action_type="block",
            message="Malaria cannot be diagnosed on tissue biopsy"
        )

# 2. Register and run
engine = GuardrailEngine()
engine.register(NoMalariaInTissueRule())

final = engine.apply(analysis, context={"sample_type": "Tissue Biopsy"})

Why

Multimodal LLMs hallucinate confidently. In medical AI, a "hallucination" isn't a funny caption — it's a biologically impossible diagnosis that could lead to real-world harm.

VLM-Guard gives you a composable, auditable rule engine to:

  • Block impossible outputs (malaria in a tissue biopsy)
  • Correct misclassifications (flagellate in blood → trypanosomiasis)
  • Promote clear patterns when the LLM is uncertain
  • Flag ambiguous findings for human review
  • Audit every modification with before/after snapshots

Installation

pip install vlm-guard

For image processing extras:

pip install vlm-guard[image]

Quick Start

1. Define your analysis schema

from vlm_guard import Analysis

result = Analysis(
    label="Malaria",
    confidence="High",
    evidence="Ring forms observed inside RBCs",
    findings="Multiple ring-stage parasites in thin blood smear",
    recommendation="Confirm species with PCR",
    metadata={"severity": "Moderate (++)", "species": "P. falciparum"}
)

2. Build rules

Rules have two methods:

  • condition(analysis, context) — should this rule fire?
  • action(analysis, context) — what to do when it fires
from vlm_guard import BaseRule, RuleResult

class SizeCheckRule(BaseRule):
    name = "size_check"
    description = "Rejects morphometrically impossible descriptions"

    def condition(self, analysis, context):
        text = (analysis.findings + " " + analysis.evidence).lower()
        return "7 μm" in text and "macrophage" in text

    def action(self, analysis, context):
        analysis.label = "Unclear"
        analysis.confidence = "Low"
        return analysis, RuleResult(
            action_taken=True, action_type="block",
            message="RBC-sized structures in macrophage cannot be amastigotes (2-4 μm)"
        )

3. Run the guardrail engine

from vlm_guard import GuardrailEngine

engine = GuardrailEngine()
engine.register(SizeCheckRule())

final, audit = engine.apply_with_audit(result, context={"sample_type": "Bone Marrow"})
print(audit.summary())
# [{"rule": "size_check", "action": "block", "message": "...", "modified": ...}]

4. End-to-end pipeline

from vlm_guard import VLMGuardPipeline
from vlm_guard.llm.parsing import parse_to_analysis
from vlm_guard.image.enhance import ImageEnhancer, EnhancementStrategy

pipeline = VLMGuardPipeline(
    model_fn=my_llm_inference_fn,      # any Callable[[Image, str], str]
    parser_fn=parse_to_analysis,        # built-in JSON parser
    guardrail_engine=engine,
    enhancer_fn=ImageEnhancer(EnhancementStrategy.HIGH_CONTRAST),
)

result = pipeline.run(image, prompt, context={"sample_type": "Blood Smear"})
print(result.analysis.label)       # final label after guardrails
print(result.audit.summary())      # everything that changed

Architecture

                     +-----------+
                     |   Image   |
                     +-----+-----+
                           |
                           v
                +----------+----------+
                |  Enhancement (opt)  |
                +----------+----------+
                           |
                           v
                +----------+----------+
                |  Multimodal LLM     |
                +----------+----------+
                           |
                           v
                +----------+----------+
                |  JSON Parser         |
                +----------+----------+
                           |
                           v
                +----------+----------+
                |  Guardrail Engine    |
                |  +-- Rule 1 (block)  |
                |  +-- Rule 2 (flag)   |
                |  +-- Rule 3 (correct)|
                |  +-- Audit Trail     |
                +----------+----------+
                           |
                           v
                +----------+----------+
                |  Final Analysis      |
                +---------------------+

Plugin System

Domain-specific rule packs can be distributed as plugins:

from vlm_guard import GuardrailEngine
from my_plugin import register_my_rules

engine = GuardrailEngine()
register_my_rules(engine)

Check the plugins/ directory for built-in examples:

  • ntd_microscopy — 12 rule classes for Neglected Tropical Disease microscopy (migrated from NTD-Assist)

Rules

VLM-Guard supports four rule types:

Type Use Case Example
Block Prevent impossible outputs Malaria on tissue biopsy → Unclear
Correct Fix misidentifications Flagellate in macrophage → Leishmaniasis
Promote Upgrade confidence when strong signal Amastigote + tissue → Leishmaniasis
Flag Lower confidence / append to recommendation "Ambiguous morphology, manual review suggested"

Extending

VLM-Guard is model-agnostic. The pipeline accepts any Callable[[Image, str], str]:

  • HuggingFace transformers models
  • OpenAI / Anthropic API clients
  • Local GGUF inference
  • Mock models for testing

License

MIT

Citation

@software{vlmguard2026,
  title = {VLM-Guard: Verification Layer for Multimodal LLMs},
  author = {Fakhry, Mohamed},
  year = {2026},
  url = {https://github.com/MohamedFakhry2007/vlm-guard}
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vlm_guard-0.1.0.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vlm_guard-0.1.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file vlm_guard-0.1.0.tar.gz.

File metadata

  • Download URL: vlm_guard-0.1.0.tar.gz
  • Upload date:
  • Size: 15.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for vlm_guard-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1a9211b6f89f06b19cb6eb62aa29436bfa8f3d8b470329bc5f57ee5c067b6979
MD5 176d81d42b8068c1289e5b0a7d9d7eed
BLAKE2b-256 b6a44769fdb7cf2a856b1a4142b49ee6b9e05f45b5087f726df7407d4f64b714

See more details on using hashes here.

File details

Details for the file vlm_guard-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: vlm_guard-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for vlm_guard-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 53dd2f5b73f8c38f09bfee77816161aebe50a96fc32f0fe27d774226f76ac728
MD5 ec6f79fd0ca2c9a3c55de35ba4b710a8
BLAKE2b-256 e4bcc4e5f76cdf76115ece0d5d05e2881629c4b5c1d85786e3317f3ef5e3e10b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page