Guardrails for LLM-generated medical and health content
Project description
llm-medical-guard
Safety guardrails for LLM-generated medical and health content.
The first open-source library specifically designed to validate medical content from LLMs.
Generic guardrail tools (NeMo Guardrails, Guardrails AI, LLM Guard) handle toxicity and PII but know nothing about medicine. llm-medical-guard catches dangerous medical claims, validates dosages, flags drug interactions, detects fear-mongering tone, enforces disclaimers, and suggests safe alternatives — in 5 languages, with a CLI, pytest plugin, and streaming support.
CLI catching dangerous dosage + cure claim + missing disclaimer in real-time
Why?
LLMs confidently generate medical misinformation. A model might say "Take 50,000 IU of Vitamin D daily to cure depression" — that's a dangerous dosage with an unsubstantiated cure claim. This library catches both issues in 64µs (15,000+ checks/sec), with zero API calls.
Quick Start
pip install llm-medical-guard
Python API
from llm_medical_guard import MedicalGuard
guard = MedicalGuard()
result = guard.check(
"Take 50000 IU of vitamin D daily to cure your depression. "
"This miracle supplement has no side effects!"
)
print(result.passed) # False
print(result.severity) # Severity.DANGER
print(result.summary)
# 5/8 checks failed:
# - [DANGER] banned_expressions: 'cure', 'no side effects'
# - [WARNING] claim_severity: 'cure your depression'
# - [WARNING] disclaimer: Required medical disclaimer not found
# - [DANGER] dosage: vitamin d: 50000IU exceeds max 4000IU/day
# - [WARNING] source_attribution: No authoritative source cited
CLI
# Check text directly
llm-medical-guard check "This miracle cure has no side effects!"
# Check from file
llm-medical-guard check -f article.txt --strict
# JSON output for CI/CD
llm-medical-guard check --json "Your content here"
# Verbose mode with safe alternative suggestions
llm-medical-guard check -v "Take this to cure cancer!"
# Run benchmark
llm-medical-guard bench
# Per check: 64.0µs
# Throughput: 15,632 checks/sec
# Generate verification badge
llm-medical-guard badge "Your content" -o badge.svg
Safe Alternatives
Not just blocking — suggests compliant replacements:
for check in result.failed_checks:
if "suggestions" in check.details:
for expr, suggestion in check.details["suggestions"].items():
print(f" '{expr}' → '{suggestion}'")
# 'cure' → 'may help manage symptoms'
# 'no side effects' → 'side effects are uncommon but possible'
# 'miracle cure' → 'evidence-based treatment option'
8 Safety Checks
| Check | What it catches | Severity |
|---|---|---|
| Banned Expressions | Cure claims, fear-mongering, anti-professional statements | DANGER |
| Claim Severity | Unsubstantiated treatment/prevention claims | WARNING |
| Disclaimer | Missing medical disclaimers | WARNING |
| Source Attribution | No authoritative source cited (FDA, NIH, etc.) | WARNING |
| Dosage | Vitamin/supplement doses exceeding safe limits | DANGER |
| Drug Interaction | Known dangerous drug-drug/drug-supplement combinations | DANGER |
| Context Awareness | Fear-mongering vs. educational tone analysis | WARNING |
| Brand Mention | Pharmaceutical brand names (promotional risk) | CAUTION |
Drug Interaction Database
123 interactions included out-of-the-box (FDA/NIH sourced), extensible via custom rules:
guard = MedicalGuard()
result = guard.check("You can safely take warfarin and aspirin together.")
# FAIL: Known interaction detected: warfarin+aspirin
# "Increased risk of serious bleeding" (Source: FDA Drug Label)
Covered interactions include:
- Warfarin + NSAIDs (bleeding risk)
- SSRIs + MAOIs (serotonin syndrome)
- Statins + Grapefruit (rhabdomyolysis)
- Levothyroxine + Calcium/Iron (absorption)
- St. John's Wort + Birth Control/SSRIs/Warfarin
- Metformin + Alcohol (lactic acidosis)
- Antibiotics + Dairy/Calcium (reduced absorption)
- Opioids + Benzodiazepines (respiratory depression)
- Fluoroquinolones + QT-prolonging drugs (cardiac arrhythmia)
- Cyclosporine + Azole antifungals (nephrotoxicity)
- PPIs + Clopidogrel (reduced antiplatelet effect)
- And 110+ more covering cardiovascular, CNS, antibiotics, diabetes, supplements, GI, pain, thyroid, and immunosuppressant categories...
Note: The built-in database covers well-documented interactions sourced from FDA and NIH. It is extensible via YAML config and custom check classes for domain-specific needs.
Context-Aware Tone Analysis
Distinguishes educational content from fear-mongering and promotional content:
# Educational — PASS
guard.check("Studies show vitamin D deficiency may increase risk of certain conditions.")
# Fear-mongering — FAIL
guard.check("This deadly combination is a ticking time bomb! They're hiding the cure!")
# Promotional — FAIL
guard.check("Buy now! Limited time offer! Use discount code HEALTH50!")
Streaming Support
Check LLM output in real-time as chunks arrive:
from llm_medical_guard import StreamGuard
stream_guard = StreamGuard(locale="en")
for chunk in llm_stream:
alert = stream_guard.feed(chunk.content)
if alert:
print(f"Warning: {alert.summary}")
# Optionally stop the stream
final_result = stream_guard.finalize()
Or use the generator:
from llm_medical_guard import check_stream
for chunk, alert in check_stream(llm_chunks):
print(chunk, end="")
if alert:
print(f"\nContent flagged: {alert.summary}")
5 Languages
# English
guard = MedicalGuard(locale="en")
# Korean (한국어)
guard = MedicalGuard(locale="ko")
guard.check("이 약을 먹으면 암 예방이 됩니다!")
# Catches: "암 예방" (cancer prevention claim)
# Japanese (日本語)
guard = MedicalGuard(locale="ja")
guard.check("この薬は万能薬です。完治します。")
# Catches: "万能薬" (cure-all), "完治" (complete cure)
# Chinese (中文)
guard = MedicalGuard(locale="zh")
guard.check("这是包治百病的神药!")
# Catches: "包治百病" (cures all diseases), "神药" (miracle drug)
# Spanish (Español)
guard = MedicalGuard(locale="es")
guard.check("Esta cura milagrosa es 100% seguro!")
# Catches: "cura milagrosa" (miracle cure), "100% seguro" (100% safe)
pytest Plugin
Test your health content in CI/CD:
# conftest.py
pytest_plugins = ["llm_medical_guard.pytest_plugin"]
# test_health_content.py
def test_article_is_safe(medical_guard):
article = load_article("vitamin_d_guide.txt")
result = medical_guard.check(article)
assert result.passed, result.summary
@pytest.mark.medical_guard(locale="ko", strict=True)
def test_korean_content(medical_guard):
result = medical_guard.check("한국어 건강 콘텐츠...")
assert result.passed
pytest --medical-guard --medical-guard-locale=en --medical-guard-strict
Pre-commit Hook
Add llm-medical-guard as a pre-commit hook to automatically check staged files for unsafe medical content:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/MOB-sys/llm-medical-guard
rev: v0.2.0
hooks:
- id: llm-medical-guard
Then run:
pre-commit install
The hook will run llm-medical-guard check on all staged text files before each commit.
Verification Badge
Generate an SVG badge for your docs/website:
from llm_medical_guard import MedicalGuard
from llm_medical_guard.badge import generate_badge
guard = MedicalGuard()
result = guard.check(your_content)
generate_badge(result, "medical-guard-badge.svg")
llm-medical-guard badge -f article.txt -o badge.svg
Configuration
YAML Config
# guard_config.yaml
locale: en
strict: false
checks:
banned_expressions: true
claim_severity: true
disclaimer: true
source_attribution: false # disable for chatbot use
dosage: true
drug_interaction: true
context_awareness: true
brand_mention: false
custom_banned_expressions:
- "detox cleanse"
- "alkaline water cure"
custom_safe_alternatives:
"detox cleanse": "support your body's natural detoxification"
guard = MedicalGuard(config="guard_config.yaml")
Programmatic Config
guard = MedicalGuard(
config={
"custom_banned_expressions": ["snake oil", "miracle juice"],
"custom_brands": ["HealthMax", "VitaBoost"],
},
locale="en",
strict=True, # raises MedicalGuardError on failure
)
Selective Checks
guard = MedicalGuard(checks=["banned_expressions", "dosage", "drug_interaction"])
Framework Integrations
LangChain
from langchain_openai import ChatOpenAI
from llm_medical_guard.integrations.langchain import MedicalGuardParser
llm = ChatOpenAI(model="gpt-4o")
parser = MedicalGuardParser(locale="en")
chain = llm | parser
# Raises OutputParserException if content is unsafe
result = chain.invoke("What supplements help with sleep?")
OpenAI SDK
from llm_medical_guard.integrations.openai_wrapper import guarded_chat_completion
response, guard_result = guarded_chat_completion(
model="gpt-4o",
messages=[{"role": "user", "content": "Tell me about vitamin D dosage"}],
)
if not guard_result.passed:
print("Content flagged:", guard_result.summary)
Performance
Benchmarking llm-medical-guard (en)
10,000 iterations × 5 samples = 50,000 total checks
Per check: 64µs
Throughput: 15,600+ checks/sec
Memory: ~5MB RSS
Dependencies: pyyaml only
Zero LLM API calls. Pure regex/rule-based. Deterministic results. Runs anywhere Python runs.
Design choice: Rule-based detection is intentional. It gives you deterministic, auditable results at near-zero cost. For semantic-level validation (e.g., detecting subtly misleading claims), pair this library with an LLM-based reviewer —
llm-medical-guardhandles the fast, cheap first pass.
Dosage Database
Built-in safe dosage limits for 10 common supplements:
| Supplement | Max Daily | Warning Threshold | Unit |
|---|---|---|---|
| Vitamin D | 4,000 | 10,000 | IU |
| Vitamin C | 2,000 | 5,000 | mg |
| Iron | 45 | 100 | mg |
| Calcium | 2,500 | 4,000 | mg |
| Zinc | 40 | 100 | mg |
| Omega-3 | 3,000 | 5,000 | mg |
| Magnesium | 400 | 800 | mg |
| Melatonin | 5 | 20 | mg |
| Vitamin A | 3,000 | 10,000 | mcg |
| Vitamin B6 | 100 | 200 | mg |
Extending
Custom Check
from llm_medical_guard.checks import BaseCheck, CheckRegistry
from llm_medical_guard.result import CheckResult, CheckStatus, Severity
@CheckRegistry.register
class MyCustomCheck(BaseCheck):
name = "my_check"
description = "My custom medical content check"
def run(self, text, config):
if "unapproved" in text.lower():
return CheckResult(
check_name=self.name,
status=CheckStatus.FAIL,
severity=Severity.WARNING,
message="Unapproved content detected",
)
return CheckResult(
check_name=self.name,
status=CheckStatus.PASS,
severity=Severity.INFO,
message="OK",
)
Custom Locale
Create a YAML file following the format in src/llm_medical_guard/i18n/en.yaml:
guard = MedicalGuard(locale="de") # will look for i18n/de.yaml
Why Not Use General Guardrails?
| Feature | llm-medical-guard | NeMo Guardrails | Guardrails AI | LLM Guard |
|---|---|---|---|---|
| Medical claim detection | Yes | No | No | No |
| Drug interaction checking | Yes | No | No | No |
| Dosage validation | Yes | No | No | No |
| Safe alternatives | Yes | No | No | No |
| Context-aware tone analysis | Yes | No | No | No |
| Medical disclaimer enforcement | Yes | No | No | No |
| Source attribution check | Yes | No | No | No |
| Multi-language medical rules | 5 | No | Partial | No |
| Streaming support | Yes | Yes | No | No |
| pytest plugin | Yes | No | Yes | No |
| CLI tool | Yes | No | Yes | Yes |
| Zero API cost | Yes | No | Partial | Yes |
| Performance | 64µs/check | ~100ms | ~50ms | ~10ms |
Roadmap
v0.3 — Data Expansion
-
Expanded drug interaction database (100+ interactions)— Done! 123 interactions - Expanded dosage limits (30+ supplements/vitamins)
- German (de), French (fr), Portuguese (pt) locales
v0.4 — Developer Tooling
- Pre-commit hook (
llm-medical-guardas a pre-commit check) - VS Code extension (inline warnings)
- Anthropic SDK integration
v1.0 — Enterprise
- ICD-10 code detection
- FHIR resource validation
- EU AI Act compliance report generation
- Semantic-level validation (optional LLM-backed deep check)
Contributing
Contributions welcome! See CONTRIBUTING.md for guidelines.
Priority areas:
- New locale files (de, fr, pt, ar, hi)
- Additional drug interaction data
- More dosage limits
- Better regex patterns to reduce false positives
- Integration with more LLM frameworks (Anthropic SDK, LlamaIndex)
License
MIT — Use freely in commercial and open-source projects.
Disclaimer
This library is a development tool for content safety screening. It does not provide medical advice and is not a substitute for professional medical review. Always have medical content reviewed by qualified healthcare professionals before publication.
Built with domain expertise from Pillright — a drug interaction checker serving 500K+ users.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_medical_guard-0.3.0.tar.gz.
File metadata
- Download URL: llm_medical_guard-0.3.0.tar.gz
- Upload date:
- Size: 757.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cac0fafe6e6f1da7525b99cc46d07fb0db4077c4d09366c36c598a5f5b6fa963
|
|
| MD5 |
32a6c77cf982170dfda43e61b2fea3e0
|
|
| BLAKE2b-256 |
daf8e443daa92d794ccdebd1a393a77f53238632f4a1b9e16faede09deb31106
|
File details
Details for the file llm_medical_guard-0.3.0-py3-none-any.whl.
File metadata
- Download URL: llm_medical_guard-0.3.0-py3-none-any.whl
- Upload date:
- Size: 63.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00cff54f958c9c9ad7564cf3362e541e8e4dcb3a61d02681a4a2447b93f5f511
|
|
| MD5 |
c76520c8651e5a64dacad4ceb4686784
|
|
| BLAKE2b-256 |
bfb1debe4c3b141f26d180bc7543a3c0ae7083182078fd5989cc3ed64e085872
|