A Semantic Type System for AI outputs — validate intent, not just shape.
Project description
semantix-ai
Validate what your LLM outputs mean, not just their shape.
pip install semantix-ai
from semantix.testing import assert_semantic
def test_chatbot_is_polite():
response = my_chatbot("handle angry customer")
assert_semantic(response, "polite and professional")
Runs locally. ~15ms. No API key. Works in pytest, unittest, or any test runner.
pytest plugin: pip install pytest-semantix for fixtures, markers, and CI reporting. See pytest-semantix.
On failure:
AssertionError: Semantic check failed (score=0.12)
Intent: polite and professional
Output: "You're an idiot for asking that."
Reason: Text contains aggressive language
What It Does
semantix validates that LLM outputs mean the right thing — using a local NLI model, not string matching or another LLM call.
from semantix import Intent, validate_intent
class ProfessionalDecline(Intent):
"""The text must politely decline an invitation without being rude."""
@validate_intent
def decline_invite(event: str) -> ProfessionalDecline:
return call_my_llm(event)
result = decline_invite("the company retreat")
# Returns a validated ProfessionalDecline — or raises SemanticIntentError
Key properties:
- Local inference — NLI model runs on CPU, no data leaves your machine
- ~15ms per check — negligible overhead on any LLM call
- Zero API cost — no tokens burned for validation
- 248 tests — well-tested, MIT licensed
Compliance with Negation
Block what your model must NOT say — PII, medical advice, competitor mentions:
from semantix import Intent, Not
class MedicalAdvice(Intent):
"""The text provides medical diagnoses or treatment recommendations."""
Safe = ~MedicalAdvice # or Not(MedicalAdvice)
@validate_intent
def chatbot(msg: str) -> Safe:
return call_my_llm(msg)
Compose with & (all must pass) and | (any must pass):
SafeAndPolite = Polite & ~MedicalAdvice & ~LegalAdvice
Self-Healing Retries
On failure, semantix injects structured feedback so the LLM knows what went wrong:
from typing import Optional
@validate_intent(retries=2)
def decline(event: str, semantix_feedback: Optional[str] = None) -> ProfessionalDecline:
prompt = f"Decline this invite: {event}"
if semantix_feedback:
prompt += f"\n\n{semantix_feedback}"
return call_llm(prompt)
First call: semantix_feedback is None. On retry: it receives a Markdown report with the score, reason, and rejected output. Reliability improves from 21% to 70% across 3 intent categories.
Framework Integrations
Drop into your existing stack — retries are handled natively by each framework.
Guardrails AI
from guardrails import Guard
from semantix.integrations.guardrails import SemanticIntent
guard = Guard().use(SemanticIntent("must be polite and professional"))
result = guard.validate("Thank you for your patience.")
Instructor
from semantix.integrations.instructor import SemanticStr
from pydantic import BaseModel
class Response(BaseModel):
reply: SemanticStr["must be polite and professional", 0.85]
Pydantic AI
from pydantic_ai import Agent
from semantix.integrations.pydantic_ai import semantix_validator
agent = Agent("openai:gpt-4o", output_type=str)
agent.output_validator(semantix_validator(Polite))
LangChain
from semantix.integrations.langchain import SemanticValidator
validator = SemanticValidator(Polite)
chain = prompt | llm | StrOutputParser() | validator
DSPy
import dspy
from semantix.integrations.dspy import semantic_reward
qa = dspy.ChainOfThought("question -> answer")
refined = dspy.Refine(module=qa, N=3, reward_fn=semantic_reward(Polite))
Install extras: pip install "semantix-ai[instructor]", "semantix-ai[pydantic-ai]", "semantix-ai[langchain]", "semantix-ai[guardrails]", "semantix-ai[dspy]"
GitHub Actions
- uses: labrat-akhona/semantic-test-action@v1
with:
test-path: tests/
Posts a semantic test report as a PR comment. See semantic-test-action.
Self-Training Flywheel
Every retry produces labeled training data — rejected output, reason, corrected output:
from semantix.training import TrainingCollector
from semantix.training.exporters import export_openai
collector = TrainingCollector("training_data.jsonl")
@validate_intent(retries=2, collector=collector)
def decline(event: str) -> ProfessionalDecline:
return call_my_llm(event)
# Export to OpenAI fine-tuning format
export_openai("training_data.jsonl", "finetune.jsonl")
Your guardrail becomes your training pipeline:
Validate → Fail → Correct → Capture → Fine-tune → Validate (fewer failures)
Pluggable Judges
Choose the right speed/accuracy tradeoff:
from semantix import NLIJudge, EmbeddingJudge, LLMJudge, CachingJudge
# Default — local NLI entailment (no API key, ~15ms)
@validate_intent(judge=NLIJudge())
# Fast — local cosine similarity (~5ms)
@validate_intent(judge=EmbeddingJudge())
# Accurate — GPT-4o-mini with 0-1 scoring + reason
@validate_intent(judge=LLMJudge(model="gpt-4o-mini"))
# Cached — wraps any judge with LRU cache
@validate_intent(judge=CachingJudge(NLIJudge(), maxsize=256))
Quantized mode for minimal footprint (~25MB vs ~500MB for PyTorch):
pip install "semantix-ai[turbo]"
# Automatically uses QuantizedNLIJudge (INT8 ONNX, no PyTorch)
Advanced Features
Forensic analysis — token-level attribution on failure:
from semantix import ForensicJudge, QuantizedNLIJudge
judge = ForensicJudge(QuantizedNLIJudge())
# Verdict.reason: "Suspect Tokens: [indemnify, forfeit, waive]"
Streaming — validate once the full stream is assembled:
from semantix import StreamCollector
for chunk in StreamCollector(Polite, judge=my_judge).wrap(llm_stream()):
print(chunk, end="")
Audit trail — hash-chained JSON-LD certificates:
from semantix.audit.engine import AuditEngine
engine = AuditEngine()
engine.verify_chain() # True if no tampering
MCP server — any AI agent can validate intents as a tool:
pip install "semantix-ai[mcp,nli]"
mcp run semantix/mcp/server.py
Async — works transparently with async def.
Installation
pip install semantix-ai # Core (default NLI judge)
pip install "semantix-ai[turbo]" # Quantized ONNX (smallest footprint)
pip install "semantix-ai[openai]" # LLM judge (GPT-4o-mini)
pip install "semantix-ai[instructor]" # Instructor integration
pip install "semantix-ai[pydantic-ai]" # Pydantic AI integration
pip install "semantix-ai[langchain]" # LangChain integration
pip install "semantix-ai[guardrails]" # Guardrails AI integration
pip install "semantix-ai[dspy]" # DSPy integration
pip install "semantix-ai[all]" # Everything
The package name on PyPI is
semantix-ai. The import isfrom semantix import ....
Contributing
See CONTRIBUTING.md for dev setup, testing, and submission guidelines.
License
MIT — see LICENSE for details.
Built by Akhona Eland in South Africa
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 semantix_ai-0.1.12.tar.gz.
File metadata
- Download URL: semantix_ai-0.1.12.tar.gz
- Upload date:
- Size: 131.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4de072af08389dbd8c55a5d2039e9c3b1aacf32887c9e27b3b6c170734f80e9b
|
|
| MD5 |
e55c66df2cb5639333c8853041f65243
|
|
| BLAKE2b-256 |
78bdeb92e7084168d2fe5afdca2ac97ced7dc34e15736a48bc8727efef9e4256
|
File details
Details for the file semantix_ai-0.1.12-py3-none-any.whl.
File metadata
- Download URL: semantix_ai-0.1.12-py3-none-any.whl
- Upload date:
- Size: 71.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3803b6ed6a2f481b1a8e29128c0b74d14bb8bca694004dd0074ed7d1e9f3900
|
|
| MD5 |
3002593271d521a42969a3fbf005bbf8
|
|
| BLAKE2b-256 |
240ef76701ae6f1a2b6702ad0e189c8e02c3c457c8325712c499d7c1f2d932bf
|