AI-powered linting tool for code quality and validation
Project description
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. ๐ก๏ธ
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_validator-0.1.1.tar.gz.
File metadata
- Download URL: llm_validator-0.1.1.tar.gz
- Upload date:
- Size: 16.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
febaef3e4b452571d2248f1b550cd71dabbdb77c1ee505ea23a9539ef8ef5f59
|
|
| MD5 |
e62c30d0fcc1aeff0f9510827ecbb81a
|
|
| BLAKE2b-256 |
23feac8ee0d1a7f0c4346125e9cca9540fad7e945e40a80d2aaff9f37ba262c8
|
File details
Details for the file llm_validator-0.1.1-py3-none-any.whl.
File metadata
- Download URL: llm_validator-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2499061461602c7e639116cc72371b7c6f4d55f254ca6535b464dcc4ea22edd9
|
|
| MD5 |
81d96bd3f2d64dd4ed21a2c14f8075ae
|
|
| BLAKE2b-256 |
78ecc8bca8172429ec2fce3b0076a3519bcfb734c73bac36cadd7f4732140772
|