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.
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.wrapdecorator (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 defaultasynciomode, 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
BeliefExtractorprocesses the turn history and queries the configuredinternal_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
ContradictionDetectorruns 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
BeliefResolverapplies 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")