Skip to main content

Post-retrieval audit layer for RAG pipelines.

Project description

StaleGuard

StaleGuard is a post-retrieval audit layer for RAG pipelines.

It sits between retrieval and generation:

Retriever / Vector DB
        ->
Retrieved chunks
        ->
StaleGuard audit
        ->
Decision:
  FRESH
  STALE
  MIXED
  CONFLICTED
  UNKNOWN
        ->
LLM

StaleGuard does not replace retrieval. It checks whether retrieved chunks are trustworthy enough to send to the model.

Install

pip install staleguard

For local embedding and NLI models:

pip install "staleguard[local]"

For the repo demos:

pip install "staleguard[demo]"

What It Does

  • score chunk freshness from metadata, version, and date signals
  • find fresher alternatives from a corpus
  • detect contradictions with rules and optional local NLI
  • surface schema issues when retrieved metadata is incomplete
  • return a provenance object you can use in middleware or UI

Current trust order:

metadata > rules = nli

That means:

  • explicit metadata wins when it is available
  • rules and NLI are secondary evidence sources
  • if rules and NLI agree, confidence increases

Core API

The shortest path is the package-level audit(...) function.

from staleguard import audit

result = audit(
    query="How do I configure Redis Cluster in Redis 8?",
    retrieved=retriever_output,
    corpus=corpus,
)

print(result.verdict)
print(result.conflicts)
print(result.provenance)

If you want to reuse configuration across calls, use StaleGuard.

from staleguard import StaleGuard

guard = StaleGuard(use_nli=True, block_on_conflict=False)
result = guard.audit(
    query="How do I configure Redis Cluster in Redis 8?",
    retrieved=retriever_output,
    corpus=corpus,
)

For advanced integrations, the same API also accepts:

  • already-normalized chunk dicts
  • raw Chroma query results
  • LangChain-style documents
  • custom embedding / conflict providers

Normalized chunks

from staleguard import StaleGuard

guard = StaleGuard(use_nli=True)

result = guard.audit_chunks(
    query="How do I configure Redis Cluster in Redis 8?",
    retrieved_chunks=[
        {
            "id": "redis_6_cluster_001",
            "text": "Redis 6 uses requirepass configuration for cluster authentication.",
            "product": "redis",
            "topic": "cluster_configuration",
            "version": "6.2",
            "date_ts": 1640995200,
            "source": "redis-6.2-cluster.md",
            "metadata": {"status": "superseded", "superseded_by": "8.0"},
        }
    ],
    corpus=[...],
)

audit(...) and guard.audit(...) auto-detect:

  • raw Chroma query results
  • LangChain-style documents with page_content and metadata
  • already-normalized chunk dicts

The lower-level helpers still exist for direct use:

  • audit_retrieved(...)
  • audit_chroma_result(...)
  • audit_langchain_docs(...)

Verdicts

  • FRESH: retrieved context looks current
  • STALE: outdated chunks were found
  • MIXED: stale and conflicting evidence were found
  • CONFLICTED: conflicting evidence was found
  • UNKNOWN: metadata is too incomplete to make a strong judgment

If you want any conflict to block generation, set:

block_on_conflict=True

That collapses MIXED into CONFLICTED.

Middleware Pattern

This is the intended integration shape:

from staleguard import StaleGuard

guard = StaleGuard(use_nli=True, block_on_conflict=False)

def audited_retrieve(query: str, retriever_output, corpus: list[dict]):
    audit_result = guard.audit(
        query=query,
        retrieved=retriever_output,
        corpus=corpus,
    )

    if audit_result.verdict == "CONFLICTED":
        return {"block": True, "audit": audit_result}

    return {"block": False, "audit": audit_result}

The application can then:

  • send FRESH chunks to the LLM
  • replace or warn on STALE
  • block or escalate on CONFLICTED
  • show provenance on MIXED

Supported Retrieval Inputs

Chroma

from staleguard import StaleGuard

guard = StaleGuard(use_nli=True)

result = guard.audit(
    query=query,
    retrieved=chroma_result,
    corpus=corpus,
)

LangChain-style documents

from staleguard import StaleGuard

guard = StaleGuard(use_nli=True)

result = guard.audit(
    query=query,
    retrieved=docs,
    corpus=corpus,
)

The repo also exposes adapter helpers:

  • normalize_chroma_result(...)
  • normalize_langchain_docs(...)
  • normalize_chunks(...)

CLI

staleguard audit --query "How do I configure Redis Cluster in Redis 8?" --retrieved retrieved.json --corpus corpus.json
staleguard eval --corpus eval_cases/kubernetes/corpus.json --cases eval_cases/kubernetes/cases.json --use-nli

Chunk Schema

Best case input:

{
    "id": "redis_8_cluster_001",
    "text": "...",
    "product": "redis",
    "topic": "cluster_configuration",
    "version": "8.0",
    "date_ts": 1735689600,
    "source": "redis-8.0-cluster.md",
    "metadata": {
        "status": "current"
    }
}

Audit-critical fields:

  • text
  • product
  • topic
  • version
  • date_ts

If some metadata is missing, StaleGuard will:

  • infer a few safe fields from source
  • record schema_issues
  • lower confidence or return UNKNOWN when needed

Demos

Redis demo

python -m staleguard.chroma_demo

This builds a local Chroma collection and shows:

  • raw Chroma retrieval
  • normalized chunks
  • prepared chunks
  • audit result

Large engineering demo

python -m staleguard.engineering_demo

This uses a larger corpus around:

  • loop engineering
  • context engineering
  • tool loop policy
  • memory policy
  • planning
  • retrieval policy

The example intentionally includes:

  • stale 2024/2025 chunks
  • fresher 2026 replacements
  • conflicting guidance that triggers NLI

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

staleguard-0.1.1.tar.gz (31.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

staleguard-0.1.1-py3-none-any.whl (30.4 kB view details)

Uploaded Python 3

File details

Details for the file staleguard-0.1.1.tar.gz.

File metadata

  • Download URL: staleguard-0.1.1.tar.gz
  • Upload date:
  • Size: 31.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for staleguard-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7c38e4f4551dfb7fe8727e5a03dd5a1b90ecc5fa98fe9e239a2ab38e162217ff
MD5 5ed8fd0283bccb21aa8d5e15a841889b
BLAKE2b-256 67feedf0238b98d07db110ef49bde4d116c900296662a22df2c2a19fa89f76bc

See more details on using hashes here.

File details

Details for the file staleguard-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: staleguard-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 30.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for staleguard-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 16b301209d9539e0f0824827dc5a81b608faf48be995c60a4ab9de3e32863ca7
MD5 fe7ffce7a48f9a6947ca34613ae4fd98
BLAKE2b-256 c08752381e5db176efc21ad8c6e5ecfeef644a2958d46e602b370d00702d6c6a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page