Implementing Contradiction Detection in MemPalace: A Complete Technical Guide

MemPalace performs offline contradiction detection by comparing user-supplied text against a local Entity Registry and temporal Knowledge Graph, identifying similar-name confusion and relationship mismatches without requiring external API calls.

MemPalace is a privacy-first knowledge management system that maintains a personal "palace" of facts and relationships. Implementing contradiction detection in MemPalace allows the system to catch factual errors, outdated information, and potential confusions before they pollute your knowledge base. The entire detection pipeline operates locally using SQLite and JSON files, ensuring no sensitive data leaves your machine.

How Contradiction Detection Works in MemPalace

The detection system in mempalace/fact_checker.py operates as an offline validation layer. When you submit text for checking, the system cross-references two internal data structures to identify potential issues.

The Two Data Sources

MemPalace maintains two distinct knowledge stores for validation:

  1. Entity Registry – A JSON dictionary containing known people, projects, and concepts loaded via mempalace/entity_registry.py (specifically the _load_known_entities_raw function)
  2. Knowledge Graph (KG) – A temporal SQLite database stored at palace_path/knowledge_graph.sqlite3 that records relationships between entities with validity windows (e.g., "Bob is Alice's brother" valid from 2020-01-01 to null)

The Detection Pipeline

The main entry point check_text(text, palace_path) in mempalace/fact_checker.py orchestrates the validation process. It returns a list of detected issues, running two primary checks sequentially:

  • _check_entity_confusion – Identifies potential typos or similar names
  • _check_kg_contradictions – Validates relationship claims against stored facts

Core Detection Logic in fact_checker.py

The fact_checker.py module contains the primary contradiction detection engine, implementing two distinct validation strategies.

Similar-Name Confusion Detection

The _check_entity_confusion method (lines 96-149) prevents subtle data entry errors by detecting names that appear in input text but differ by ≤2 edit distance from a different registered name. This catches typical typos that might create duplicate or confused entities.

The implementation uses a fast edit-distance helper _edit_distance (lines 89-108) to compare extracted names against the Entity Registry without requiring fuzzy database queries.

Knowledge Graph Contradiction Detection

The _check_kg_contradictions method (lines 82-127) handles semantic validation by parsing relationship claims and querying the temporal Knowledge Graph. It detects two specific contradiction types:

  • Relationship mismatch – When the text claims "Bob is Alice's brother" but the KG records Bob as Alice's husband
  • Stale fact – When the claim matches a KG entry that has expired (its valid_to date precedes today)

Parsing Claims from Text

Before the Knowledge Graph can validate relationships, the system must extract structured semantic triples from unstructured text.

Regex Pattern Matching

The _extract_claims function (lines 55-79) uses compiled patterns stored in _RELATIONSHIP_PATTERNS to identify relationship statements. The default patterns recognize:

  • "X is Y's Z" (e.g., "Bob is Alice's brother")
  • "X's Z is Y" (e.g., "Alice's brother is Bob")

Each match yields a triple tuple of (subject, predicate, object) that represents the semantic claim for KG validation.

Extracting Semantic Triples

Once extracted, claims are validated against the Knowledge Graph instance created at line 104 in fact_checker.py, which points to palace_path/knowledge_graph.sqlite3. The KnowledgeGraph class defined in mempalace/knowledge_graph.py provides the query interface.

Querying the Temporal Knowledge Graph

The Knowledge Graph implementation in mempalace/knowledge_graph.py supports temporal validity, allowing facts to have finite lifespans.

Relationship Mismatch Detection

For each extracted claim, the system queries outgoing facts for the subject using query_entity(name, as_of=None, direction="outgoing"). If the KG contains a fact sharing the same object but a different predicate, the system generates a relationship_mismatch issue (lines 27-50 in fact_checker.py).

The temporal filtering uses _temporal_filter_sql to ensure only currently valid facts participate in the contradiction check unless a specific as_of date is provided.

Stale Fact Detection

When a claim exactly matches a KG entry but the entry's valid_to date (validated via sanitize_iso_temporal from mempalace/config.py) precedes the current date, the system flags a stale_fact issue (lines 52-65). This prevents users from asserting relationships that have explicitly expired.

Practical Implementation Examples

Basic Python API Usage

Import the check_text function to validate strings programmatically:

from mempalace.fact_checker import check_text

# Detect contradictions in a user message

issues = check_text(
    "Bob is Alice's brother",
    palace_path="/home/user/.mempalace/palace"
)

for issue in issues:
    print(issue["type"], "→", issue["detail"])

CLI Invocation

Run contradiction detection from the command line:

$ python -m mempalace.fact_checker "Bob is Alice's brother" \
    --palace /home/user/.mempalace/palace

When a mismatch is detected, the CLI outputs structured JSON:

[
  {
    "type": "relationship_mismatch",
    "detail": "Text says 'Bob is Alice's brother' but KG records Bob husband Alice",
    "entity": "Bob",
    "claim": {"predicate": "brother", "object": "Alice"},
    "kg_fact": {"predicate": "husband", "object": "Alice"}
  }
]

Extending Detection with Custom Patterns

Add new relationship types by appending compiled regex patterns to _RELATIONSHIP_PATTERNS in mempalace/fact_checker.py:

import re

# Add support for "works with" relationships

_RELATIONSHIP_PATTERNS.append(
    re.compile(r"\b([A-Z][\w-]+)\s+works\s+with\s+([A-Z][\w-]+)\b")
)

Now statements like "Bob works with Alice" will be parsed and validated against the Knowledge Graph.

Summary

  • MemPalace contradiction detection operates entirely offline in mempalace/fact_checker.py, comparing text against local JSON and SQLite data stores.
  • Entity confusion detection uses edit-distance calculations in _check_entity_confusion to catch typos and similar names.
  • Knowledge Graph validation extracts semantic triples via _extract_claims and checks them against temporal facts in knowledge_graph.sqlite3.
  • Two contradiction types are identified: relationship_mismatch (conflicting predicates) and stale_fact (expired validity windows).
  • Zero external dependencies preserve the privacy-first architecture—no API calls are required for fact validation.
  • Extensible architecture allows custom regex patterns and additional check functions to be integrated into the check_text pipeline.

Frequently Asked Questions

How does MemPalace handle temporal facts that change over time?

The Knowledge Graph in mempalace/knowledge_graph.py stores each relationship with optional valid_from and valid_to timestamps. When query_entity is called, the _temporal_filter_sql helper applies the as_of parameter (defaulting to the current date) to return only facts valid at that specific time. This allows the system to detect stale_fact contradictions when users assert relationships that have expired, while still maintaining historical accuracy in the database.

Can I use contradiction detection without the full MemPalace application?

Yes, the fact_checker.py module is self-contained. You can import check_text into any Python script, provided you supply a valid palace_path containing the knowledge_graph.sqlite3 file and entity registry JSON. The CLI interface also allows standalone operation via python -m mempalace.fact_checker, making it suitable for integration with external scripts or git hooks.

What edit distance threshold does MemPalace use for entity confusion detection?

The _check_entity_confusion function flags names that differ by ≤2 edit distance from a registered entity name, provided they are not identical matches. This threshold is implemented in lines 96-149 of fact_checker.py using the internal _edit_distance helper (lines 89-108), which performs a fast dynamic programming calculation optimized for short strings typical of personal knowledge bases.

How can I add support for non-English relationship patterns?

Extend the _RELATIONSHIP_PATTERNS list in mempalace/fact_checker.py with compiled regex patterns matching your target language's relationship syntax. Ensure your patterns capture named groups or return tuples matching the (subject, predicate, object) format expected by _check_kg_contradictions. Since the KG stores raw strings, non-English entities and predicates are fully supported without modification to the KnowledgeGraph class in mempalace/knowledge_graph.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →