Motivation
LettuceDetect currently relies on encoder, generative, LLM-judge, and RAGFactChecker paths. A low-compute lexical detector could handle a narrow set of obvious unsupported details before a learned detector runs, while also providing a useful baseline.
Candidate checks include:
- numbers and quantities absent from the evidence;
- dates and durations absent from the evidence;
- named entities with no exact or normalized match;
- deliberately conservative relation checks where precision can be measured.
High precision at low coverage is a useful outcome. The objective is not to replace semantic verification.
Relation to RuleChef
RuleChef can synthesize regex, Python, and spaCy rules from labeled examples. A second-stage experiment could use RAGTruth gold annotations—or observations from a LettuceDetect model—to propose candidate rules.
Synthesized rules inherit errors and biases from their teacher and examples. They must therefore be frozen and evaluated against independently held-out gold labels; generated rules are not automatically correct or fully interpretable merely because their runtime is deterministic.
Proposed first cut
- Add a
rule branch to make_detector returning a RuleBasedDetector(BaseDetector) that implements predict, predict_prompt, and predict_prompt_batch for both spans and tokens output.
- Begin with hand-written number, date, duration, and entity checks. Keep semantic embeddings out of the first implementation.
- Evaluate the tier on the RAGTruth test split and report span precision, span recall, example-level F1, and routed coverage alongside the transformer detector.
- Optionally freeze RuleChef-synthesized candidates and compare them with the hand-written tier under the same protocol.
Acceptance
HallucinationDetector(method="rule") uses the documented prediction API and requires neither torch nor an API key at runtime.
- Network-free tests cover output formats, offsets, normalization, batch length validation, and representative false-positive cases;
python -m pytest passes.
- A reproducible RAGTruth results table reports precision, recall, example-level F1, and coverage for both hand-written and synthesized variants that are attempted.
- Negative or partial results are documented and are a valid contribution.
Non-goals
- Replacing the transformer or generative detectors.
- Claiming that lexical absence proves hallucination.
- Embedding or LLM calls in the first implementation.
Start here
git clone https://github.com/KRLabsOrg/LettuceDetect.git
cd LettuceDetect
pip install -e ".[dev]"
python -m pytest
Relevant interfaces: lettucedetect/detectors/base.py, lettucedetect/detectors/factory.py, and lettucedetect/detectors/prompt_utils.py.
Motivation
LettuceDetect currently relies on encoder, generative, LLM-judge, and RAGFactChecker paths. A low-compute lexical detector could handle a narrow set of obvious unsupported details before a learned detector runs, while also providing a useful baseline.
Candidate checks include:
High precision at low coverage is a useful outcome. The objective is not to replace semantic verification.
Relation to RuleChef
RuleChef can synthesize regex, Python, and spaCy rules from labeled examples. A second-stage experiment could use RAGTruth gold annotations—or observations from a LettuceDetect model—to propose candidate rules.
Synthesized rules inherit errors and biases from their teacher and examples. They must therefore be frozen and evaluated against independently held-out gold labels; generated rules are not automatically correct or fully interpretable merely because their runtime is deterministic.
Proposed first cut
rulebranch tomake_detectorreturning aRuleBasedDetector(BaseDetector)that implementspredict,predict_prompt, andpredict_prompt_batchfor bothspansandtokensoutput.Acceptance
HallucinationDetector(method="rule")uses the documented prediction API and requires neither torch nor an API key at runtime.python -m pytestpasses.Non-goals
Start here
Relevant interfaces:
lettucedetect/detectors/base.py,lettucedetect/detectors/factory.py, andlettucedetect/detectors/prompt_utils.py.