Adapters

Adapters translate between native LLM SDK formats and BeliefState's universal models. All adapters include:

✅ Automatic Retry ✅ Timeout Handling ✅ Health Checks ✅ Structured Logging ✅ API Key Validation
🟢

OpenAI

GPT-4o, GPT-4, GPT-3.5

🟣

Anthropic

Claude 3.5, Claude 3

🔵

Gemini

Gemini 2.0, 1.5

🦙

Ollama

Llama 3, Mistral, etc.

🌐

LiteLLM

100+ providers

OpenAI

pythonfrom beliefstate.adapters import OpenAIAdapter

adapter = OpenAIAdapter(
    model="gpt-4o",                        # Chat completion model
    embed_model="text-embedding-3-small",   # Embedding model
    timeout=30.0,                           # Request timeout (seconds)
)


is_healthy = await adapter.health_check()


from beliefstate.adapters.common import RetryConfig

adapter = OpenAIAdapter(
    model="gpt-4o",
    retry_config=RetryConfig(
        max_retries=3,
        initial_delay=1.0,
        max_delay=30.0,
        exponential_base=2.0,
        jitter=True,           # Prevents thundering herd
    )
)

Set OPENAI_API_KEY environment variable or pass via api_key parameter.

Anthropic (Claude)

pythonfrom beliefstate.adapters import AnthropicAdapter

adapter = AnthropicAdapter(
    model="claude-3-5-sonnet-latest",
    timeout=30.0
)

⚠️ Note: Anthropic does not provide an embeddings API. Use the Dual-Adapter pattern with OpenAI or Ollama as the internal_adapter for embedding generation.

Google Gemini

pythonfrom beliefstate.adapters import GeminiAdapter

adapter = GeminiAdapter(
    model="gemini-2.0-flash",
    embed_model="text-embedding-004",
    timeout=30.0
)

Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable.

Ollama (Local)

pythonfrom beliefstate.adapters import OllamaAdapter

adapter = OllamaAdapter(
    model="llama3.2",
    embed_model="nomic-embed-text",
    host="http://localhost",
    port=11434
)

💡 Tip: Ollama is perfect as an internal_adapter in the Dual-Adapter pattern — completely free, fast, and runs locally.

LiteLLM (Multi-Provider)

pythonfrom beliefstate.adapters import LiteLLMAdapter


adapter = LiteLLMAdapter(
    model="azure/gpt-4",                    # Azure OpenAI
    embed_model="cohere/embed-english-v3.0"  # Cohere embeddings
)


adapter = LiteLLMAdapter(model="bedrock/anthropic.claude-3-sonnet")

Dual-Adapter Architecture

Use a premium model for your application and a cheaper/local model for background tracking to optimize costs:

pythonfrom beliefstate.adapters import AnthropicAdapter, OllamaAdapter


app_adapter = AnthropicAdapter(model="claude-3-5-sonnet-latest")


bg_adapter = OllamaAdapter(model="llama3", embed_model="nomic-embed-text")

tracker = BeliefTracker(
    config=config,
    adapter=app_adapter,              # Intercepts the Claude API payload
    internal_adapter=bg_adapter       # Runs extraction, embeddings, and judge
)
  ┌─────────────────────┐                 ┌─────────────────────┐
  │   App Adapter       │                 │  Internal Adapter   │
  │ (Claude 3.5 Sonnet) │                 │  (Ollama / Llama3)  │
  │                     │                 │                     │
  │  • to_llm_call()    │                 │  • generate()       │
  │  • to_llm_response()│    ────────▶    │  • get_embeddings() │
  │  (payload parsing)  │  belief tasks   │  • health_check()   │
  └─────────────────────┘                 └─────────────────────┘

Payload Normalization Design

Different model providers use radically different SDK payload signatures. For example:

  • OpenAI: Accesses response text via response.choices[0].message.content.
  • Anthropic: Accesses response text via response.content[0].text.
  • Google Gemini: Accesses response text via response.text.

To enable universal tracking, each adapter implements the ProviderAdapter protocol to normalize inputs and outputs:

  • to_llm_call(*args, **kwargs): Intercepts raw arguments passed to the provider SDK and extracts the conversation history, converting them into a standardized LLMCall structure containing a unified list of message dictionaries.
  • to_llm_response(raw_response): Normalizes the provider's returned response object into an LLMResponse structure, exposing the message content, model name, and token usage metadata.

This decoupling is what enables the **Dual-Adapter** pattern: the premium adapter parses the main application LLM calls, while the internal adapter handles all background vector embeddings, fact extractions, and logical checks using completely different API calls (or a local instance like Ollama).