✨ Open Source · MIT Licensed

BeliefState

An asynchronous, zero-latency belief state tracking layer for Python. Seamlessly intercepts LLM conversations, extracts factual beliefs, resolves contradictions, and saves them to persistent storage — completely in the background.

$ pip install beliefstate 📋
Get Started →

Zero-Latency

Fire-and-forget background tasks. Your app never waits for extraction or contradiction detection.

🔌

5 Providers

Native adapters for OpenAI, Anthropic, Gemini, Ollama, and LiteLLM with automatic retry and health checks.

🧠

Smart Contradictions

Semantic embeddings + NLI judge to detect and resolve conflicting beliefs automatically.

🏗️

Dual-Adapter

Use an expensive model for your app and a cheap/local model for background tracking.

🛡️

Production-Grade

Circuit breakers, exponential backoff, health checks, OpenTelemetry tracing, and structured logging.

🔗

Plug-and-Play

Middleware for FastAPI, Flask, ASGI, and callbacks for LangChain, LlamaIndex, and OpenAI Assistants.

Installation

Install the core package with pip. BeliefState requires Python 3.10+.

Core Package

# Core package (includes SQLite store, async tracker)
pip install beliefstate

With Extras

Install optional provider adapters, stores, and integrations as needed:

# Individual providers
pip install "beliefstate[openai]"
pip install "beliefstate[anthropic]"
pip install "beliefstate[gemini]"
pip install "beliefstate[ollama]"
pip install "beliefstate[litellm]"

# Stores
pip install "beliefstate[redis]"

# Framework integrations
pip install "beliefstate[fastapi]"
pip install "beliefstate[flask]"
pip install "beliefstate[langchain]"
pip install "beliefstate[llamaindex]"

# Background workers
pip install "beliefstate[celery]"
pip install "beliefstate[rq]"

# Everything
pip install "beliefstate[all]"

Quickstart

The fastest way to start tracking beliefs is the @tracker.wrap decorator. It transparently intercepts your LLM call, extracts beliefs from the conversation, and stores them — all without blocking your application.

pythonimport asyncio
from beliefstate import BeliefTracker, TrackerConfig
from beliefstate.adapters import OpenAIAdapter

# 1. Configure the tracker
config = TrackerConfig(
    enable_background_tasks=True,
    store_type="sqlite",
    store_kwargs={"db_path": "user_beliefs.db"}
)

# 2. Initialize adapter and tracker
adapter = OpenAIAdapter(model="gpt-4o", embed_model="text-embedding-3-small")
tracker = BeliefTracker(config=config, adapter=adapter)

# 3. Wrap your LLM function — that's it!
@tracker.wrap
async def chat(messages):
    import openai
    client = openai.AsyncClient()
    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    return response

async def main():
    # Set the active session
    tracker.set_session("user_123")

    # Run normally — beliefs are extracted silently in the background
    await chat([{"role": "user", "content": "I'm a Python developer living in Tokyo."}])

    # Later, retrieve beliefs as a context prompt
    context = await tracker.get_context_prompt()
    print(context)
    # Output: "USER is Python developer\nUSER lives in Tokyo"

if __name__ == "__main__":
    asyncio.run(main())

💡 Tip: Call tracker.get_context_prompt() to get formatted beliefs for injecting into your system prompt. This gives your LLM persistent memory across conversations.

Core Concepts

BeliefState follows a simple 3-stage pipeline that runs entirely in the background:

  ┌──────────────┐     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
  │   LLM Call   │────▶│   Extract    │────▶│   Detect     │────▶│   Resolve    │
  │ (Your App)   │     │   Beliefs    │     │ Contradicts  │     │ & Store      │
  └──────────────┘     └──────────────┘     └──────────────┘     └──────────────┘
        │                     │                    │                     │
    @tracker.wrap        BeliefExtractor    ContradictionDetector   BeliefResolver
    intercepts call      LLM-based parse    Embedding similarity    Overwrite /
    non-blocking         subject-pred-val   + NLI Judge scoring     Keep / Raise

Pipeline Mechanics

The belief state tracking process executes asynchronously through five discrete stages:

  • 1. Interception: The @tracker.wrap decorator (or web framework middleware) intercepts the request payload and response text of your application's LLM calls, recording the conversation turns without modifying the application's runtime.
  • 2. Asynchronous Dispatch: To achieve zero-latency overhead for your end users, the tracking payload is passed to a pluggable Dispatcher. In default asyncio mode, this registers a background task in the running event loop; in distributed environments, it serializes and offloads the task to Celery or RQ workers.
  • 3. Fact Extraction: The BeliefExtractor processes the turn history and queries the configured internal_adapter. The model parses the conversation context and extracts declarative facts structured as subject-predicate-value triples, along with confidence estimations.
  • 4. Contradiction Detection: Newly extracted facts are compared against existing beliefs for the session. The ContradictionDetector runs a two-step filter:
    • Semantic Filtering: Filters stored beliefs using cosine similarity of embedding vectors, focusing only on conceptually related claims.
    • Logical Judgment: Selected candidate pairs are analyzed by a Natural Language Inference (NLI) judge to determine if they entail (duplicate) or contradict the existing state.
  • 5. Conflict Resolution & Storage: If a contradiction is detected, the BeliefResolver applies a resolution policy (such as overwriting with the newer claim, retaining the old belief, or raising an exception). Resolved facts are then persisted to the store.

Beliefs

A Belief is a structured fact extracted from conversation text. Each belief is a subject-predicate-value triple with metadata:

pythonfrom beliefstate import Belief

belief = Belief(
    subject="USER",           # Who/what this is about
    predicate="lives in",      # The relationship
    value="Tokyo",             # The value
    confidence=1.0,            # 0.0–1.0 extraction confidence
    turn=3,                    # Conversation turn number
    source="user",             # "user" or "assistant"
    belief_type="assertion",    # "assertion" or "update"
    is_hypothetical=False,     # Skip hypothetical beliefs in prompts
)

Sessions & Conversations

BeliefState uses a session model for grouping beliefs by user, and optionally by conversation thread:

python# Set session (required)
tracker.set_session("user_123")

# Optionally set conversation within the session
tracker.set_conversation("conv_abc")

# Retrieve beliefs scoped to conversation
context = await tracker.get_context_prompt(conversation_id="conv_abc")