Negation & polarity awareness for semantic caches — stop serving 'enable' when the user asked 'disable'.
Project description
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.
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 recalq_guard-0.1.0.tar.gz.
File metadata
- Download URL: recalq_guard-0.1.0.tar.gz
- Upload date:
- Size: 5.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f84410fc48ac4868add62b53710d330036fe2effd4052c0f56e005e8b345dfc6
|
|
| MD5 |
51c7a7582371c715073f642d6d3d297e
|
|
| BLAKE2b-256 |
5c74dfa6a889f9e39c1fed23f5b0d6728d7b3cd8fa5f7bdf445333d9f098db82
|
File details
Details for the file recalq_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: recalq_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d4ff6543ebde5586f701e6359e346d2533029041741bb4208b88594d8a1550b
|
|
| MD5 |
2a86af26578672cf46f80d32ec2cf8f3
|
|
| BLAKE2b-256 |
f50a3457d5741fb0ff6df245e7c015d49866d1e7d6555c3fe3f01f56aea337a3
|