recalq-guard
Stop your semantic cache from serving "enable" when the user asked "disable".
Plain semantic caching returns a cached answer whenever cosine similarity clears a threshold. But "how to enable ssh root login" and "how to disable ssh root login" are 95%+ similar — and have opposite answers. Serving the wrong one is a security incident.
recalq-guard is a tiny, zero-dependency layer that catches these before you serve them. Wrap any semantic cache (LiteLLM, Portkey, your own) with one check.
from recalq_guard import is_safe_match
if is_safe_match(user_query, cached_query):
return cached_answer # safe to serve
else:
call_the_llm() # polarity/concept conflict — don't serve a wrong answer
Install
pip install recalq-guard
Zero heavy dependencies. Pure Python. Works with any embedding model or cache backend — it inspects the text, not the vectors.
The problem it solves
Semantic caches match by meaning-similarity. That's great — until meaning flips on a word:
| User asks | Cache has | Cosine sim | Plain cache | Correct? |
|---|---|---|---|---|
| how to disable ssh root | how to enable ssh root | ~0.95 | serves "enable" answer | WRONG |
| how to decrease memory | how to increase memory | ~0.94 | serves "increase" answer | WRONG |
| how to block port 22 | how to allow port 22 | ~0.92 | serves "allow" answer | WRONG |
recalq-guard catches all three.
Benchmark
Head-to-head on adversarial queries (same embedding model, same threshold; only the matching logic differs):
Dangerous cases (must reject): 9
Plain semantic cache — wrong: 3/9 (enable/disable, increase/decrease, allow/block)
recalq-guard — wrong: 0/9
Legitimate rephrasings (should match): 2
Plain — missed: 0/2
recalq-guard — missed: 0/2
Plain caching served 3 wrong answers. recalq-guard served 0 — without breaking a single legitimate match.
Run it yourself: python3 benchmark.py
How it works
Three checks, all pure-text, no LLM call, sub-millisecond:
- Polarity conflict — opposite sides of an antonym pair (enable/disable, start/stop, allow/deny, +25 more, customizable).
- Negation asymmetry — one query says "without/not/never", the other doesn't.
- Concept gap — the distinctive content words don't sufficiently overlap (catches entity swaps like nginx↔apache).
Customize
from recalq_guard import Guard
guard = Guard(
polarity_pairs=[("promote", "demote"), ("scale up", "scale down")], # add your domain's antonyms
min_concept_overlap=0.6,
)
result = guard.evaluate("how to demote a node", "how to promote a node")
print(result.safe, result.reason) # False, "polarity conflict: 'promote' vs 'demote'"
LiteLLM integration
See examples/litellm_integration.py — one wrapper function turns plain caching into negation-aware caching.
Why this exists
recalq-guard is the open-source safety layer extracted from Recalq — a private semantic orchestration engine that adds intent-aware routing and compositional answer synthesis on top of caching. The negation guard is the piece that's useful to everyone, so it's open. The orchestration engine is not public.
If you're working on semantic caching, routing, or LLM infrastructure and want to talk about the rest, reach out.
License
MIT.
Release files for recalq-guard 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| recalq_guard-0.1.0.tar.gz | 5.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| recalq_guard-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.6 kB
Release files / recalq_guard-0.1.0.tar.gz
| Download URL | recalq_guard-0.1.0.tar.gz |
|---|---|
| Size | 5.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f84410fc48ac4868add62b53710d330036fe2effd4052c0f56e005e8b345dfc6
|
|
BLAKE2b-256 checksum How to use checksums |
5c74dfa6a889f9e39c1fed23f5b0d6728d7b3cd8fa5f7bdf445333d9f098db82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|
Release files / recalq_guard-0.1.0-py3-none-any.whl
| Download URL | recalq_guard-0.1.0-py3-none-any.whl |
|---|---|
| Size | 6.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1d4ff6543ebde5586f701e6359e346d2533029041741bb4208b88594d8a1550b
|
|
BLAKE2b-256 checksum How to use checksums |
f50a3457d5741fb0ff6df245e7c015d49866d1e7d6555c3fe3f01f56aea337a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.25
|