LintAI - AI Output Testing & Validation Framework
A production-ready framework for validating AI/LLM outputs against user-defined assertions, confidence scoring, and edge case testing.
📦 Installation
From PyPI (Recommended)
pip install llm-validator
From Source
git clone https://github.com/SoulSniper-V2/lintai.git
cd lintai
pip install -e .
🎯 Features
- ✅ Assertion-Based Validation - Define expected behavior with simple rules
- 📊 Confidence Scoring - Get quantified trust metrics for outputs
- 🧪 Edge Case Testing - Systematically test boundary conditions
- 🤖 Multi-Model Support - Works with OpenAI, Anthropic, Gemini, local LLMs
- 📈 Regression Tracking - Track validation scores over time
- 🔄 CI/CD Integration - Run validations in GitHub Actions pipelines
- 🚀 Auto-Release to PyPI - Tags automatically publish to PyPI
🚀 Quick Start
CLI Usage
# Initialize a validation config
lintai init-config
# Validate with a config file
lintai validate --config validators/my_config.yaml
# Batch validation from JSONL
lintai batch --input test_cases.jsonl --output results.jsonl
from llm_validator import LLMValidator, Assertion, AssertionType
# Initialize validator
validator = LLMValidator(
model="gpt-4",
api_key="your-key"
)
# Define assertions
assertions = [
Assertion(
name="max_length",
type=AssertionType.MAX_LENGTH,
params={"max_tokens": 500},
weight=0.3
),
Assertion(
name="no_profanity",
type=AssertionType.NO_PATTERN,
params={"pattern": r"(?i)badword|offensive"},
weight=0.5
),
Assertion(
name="contains_action_plan",
type=AssertionType.CONTAINS_TEXT,
params={"text": "step 1", "count": 1},
weight=0.2
)
]
# Validate output
result = validator.validate(
prompt="Create a plan to increase sales",
output="Here is a step by step plan...",
assertions=assertions
)
print(f"Confidence Score: {result.score}/100")
print(f"Passed: {result.passed}")
print(f"Failed: {result.failed_assertions}")
CLI Usage
# Run validation from config
llm-validate --config validators/sales_plan.yaml
# Quick test
llm-validate --prompt "Summarize this" --output "The text says..." --rules "max_tokens:100"
# Batch validation
llm-validate --input test_cases.jsonl --output results.jsonl
Web Dashboard
cd frontend
npm install
npm run dev
Access at http://localhost:5173
📁 Project Structure
llm-validator/
├── llm_validator/
│ ├── __init__.py
│ ├── core.py # Main validation logic
│ ├── assertions.py # Assertion types
│ ├── models.py # Data models
│ └── providers.py # LLM provider integration
├── frontend/
│ ├── src/
│ │ ├── App.jsx
│ │ └── components/
│ ├── package.json
│ └── vite.config.js
├── tests/
│ ├── test_core.py
│ └── test_assertions.py
├── validators/ # Example validation configs
├── README.md
└── requirements.txt
🛠️ Assertion Types
| Type | Description | Example |
|---|---|---|
MAX_LENGTH |
Output within token/char limit | max_tokens: 1000 |
MIN_LENGTH |
Output meets minimum length | min_words: 50 |
CONTAINS_TEXT |
Output has required text | text: "step 1" |
NO_PATTERN |
Output doesn't match pattern | pattern: "error|fail" |
REGEX_MATCH |
Output matches regex | pattern: r"^\d+\." |
SENTIMENT |
Output sentiment check | min_positive: 0.6 |
JSON_VALID |
Output is valid JSON | schema: ./schema.json |
KEYWORD_COUNT |
Keywords present | keywords: ["AI", "ML"] |
CUSTOM |
Python function validation | function: my_validator.py |
📊 Confidence Scoring
The validator calculates a weighted confidence score:
Confidence Score = Σ(passed_weight) / Σ(total_weight) × 100
Individual assertion results:
- ✅ PASS: Assertion met
- ❌ FAIL: Assertion not met
- ⚠️ WARN: Assertion partially met (with penalty)
🎨 Example Validators
Code Review Validator
name: code_review
model: gpt-4
assertions:
- name: has_tests
type: CONTAINS_TEXT
params: { text: "test" }
weight: 0.3
- name: no_hardcoded_secrets
type: NO_PATTERN
params: { pattern: "api_key|password|secret" }
weight: 0.4
- name: reasonable_length
type: MAX_LENGTH
params: { max_tokens: 2000 }
weight: 0.2
- name: has_error_handling
type: REGEX_MATCH
params: { pattern: "except|try|catch" }
weight: 0.1
Customer Email Validator
name: customer_email
model: claude-3-opus
assertions:
- name: professional_tone
type: SENTIMENT
params: { min_positive: 0.3, max_negative: 0.2 }
weight: 0.3
- name: has_greeting
type: CONTAINS_TEXT
params: { text: "Dear|Hello|Hi" }
weight: 0.1
- name: has_signature
type: CONTAINS_TEXT
params: { text: "Sincerely|Best|Thanks" }
weight: 0.1
- name: no_pii
type: NO_PATTERN
params: { pattern: "\\d{3}-\\d{2}-\\d{4}" } # SSN pattern
weight: 0.5
🔧 Configuration
Environment Variables
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=...
GOOGLE_API_KEY=...
Provider Selection
from llm_validator.providers import OpenAIProvider, AnthropicProvider, LocalProvider
# OpenAI
validator = LLMValidator(provider=OpenAIProvider(model="gpt-4"))
# Anthropic
validator = LLMValidator(provider=AnthropicProvider(model="claude-3-opus"))
# Local/Ollama
validator = LLMValidator(provider=LocalProvider(model="llama2"))
🧪 Testing
# Run all tests
pytest tests/
# Run with coverage
pytest --cov=llm_validator tests/
# Run specific test
pytest tests/test_core.py -v
📈 CI/CD Integration
GitHub Actions
name: Validate AI Outputs
on: [push]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with: { python-version: '3.11' }
- name: Install
run: pip install llm-validator
- name: Run Validation
run: |
llm-validate \
--config validators/code_review.yaml \
--output validation_results.json
- name: Check Score
run: |
if [ $(jq '.score' validation_results.json) -lt 80 ]; then
echo "Score below threshold!"
exit 1
fi
🎯 Use Cases
- Production AI Safety: Validate outputs before showing to users
- Code Review Automation: Check AI-generated code for quality
- Content Moderation: Ensure outputs meet guidelines
- Customer Support: Validate response quality
- RAG Evaluation: Test retrieval-augmented generation accuracy
- Model Comparison: Compare output quality across models
🤝 Contributing
- Fork the repo
- Create a feature branch
- Add your assertion type
- Submit a PR
🔄 Automated Releases
This project uses GitHub Actions for CI/CD:
| Workflow | Description |
|---|---|
| Test | Runs pytest on every push/PR |
| Build | Builds PyPI package on every push |
| Publish | Auto-publishes to PyPI when a git tag is pushed |
How to Release
# Make changes, commit
git add -A
git commit -m "Description of changes"
# Create a version tag (follows semver)
git tag v0.1.1
# Push tag to trigger PyPI release
git push origin main
git push origin v0.1.1
The CI workflow will:
- Run tests
- Build the package
- Publish to PyPI automatically
Note: Requires PYPI_API_TOKEN secret in GitHub repo settings.
📄 License
MIT License - Build, validate, ship with confidence!
Never deploy AI without validation. 🛡️
Metadata
Release files for llm-validator 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| llm_validator-0.1.1.tar.gz | 16.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| llm_validator-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.7 kB
Release files / llm_validator-0.1.1.tar.gz
| Download URL | llm_validator-0.1.1.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
febaef3e4b452571d2248f1b550cd71dabbdb77c1ee505ea23a9539ef8ef5f59
|
|
BLAKE2b-256 checksum How to use checksums |
23feac8ee0d1a7f0c4346125e9cca9540fad7e945e40a80d2aaff9f37ba262c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|
Release files / llm_validator-0.1.1-py3-none-any.whl
| Download URL | llm_validator-0.1.1-py3-none-any.whl |
|---|---|
| Size | 14.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2499061461602c7e639116cc72371b7c6f4d55f254ca6535b464dcc4ea22edd9
|
|
BLAKE2b-256 checksum How to use checksums |
78ecc8bca8172429ec2fce3b0076a3519bcfb734c73bac36cadd7f4732140772
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|
Security for llm-validator 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.