Skip to main content

Bayesian decision-theoretic agents — expected utility maximisation, not prompt engineering

Project description

Credence

Bayesian decision-theoretic agents — a reusable library and an empirical benchmark.

Credence provides domain-agnostic Bayesian agents that learn tool reliability from experience, use value-of-information calculations to decide when to query and when to abstain, and adapt when reliability changes. No heuristics, no hardcoded routing — just expected utility maximisation.

The project also includes a head-to-head benchmark comparing the Bayesian agent against LangChain ReAct agents on a multi-tool question-answering task.

Using Credence as a Library

# Core library (numpy + scipy only)
uv sync

# With benchmark dependencies (matplotlib, langchain, etc.)
uv sync --extra benchmark

# With dev tools (pytest, ruff, etc.)
uv sync --extra dev

Facade import

from credence import BayesianAgent, ToolConfig, ScoringRule

Minimal custom-domain example

import numpy as np
from credence import BayesianAgent, ToolConfig, ScoringRule

# Define your domain's categories and tools
categories = ("plot", "character", "setting", "theme")
num_cats = len(categories)
tools = [
    ToolConfig(cost=1.0, coverage_by_category=np.ones(num_cats)),   # wiki_search
    ToolConfig(cost=3.0, coverage_by_category=np.ones(num_cats)),   # deep_read
    ToolConfig(cost=2.0, coverage_by_category=np.ones(num_cats)),   # summary_llm
]

# Category inference: question text -> probability vector over categories
# (or use make_keyword_category_infer_fn for keyword-based heuristics)
def infer_category(text: str) -> np.ndarray:
    return np.ones(num_cats) / num_cats  # uniform prior

agent = BayesianAgent(
    tool_configs=tools,
    categories=categories,
    category_infer_fn=infer_category,
)

Categories, tools, scoring rules, and the category inference function are all injected — the agent itself is domain-agnostic.

The Benchmark

A head-to-head comparison between a Bayesian decision-theoretic agent and LangChain ReAct agents on a multi-tool question-answering task.

Both agents have access to the same four tools with heterogeneous, category-dependent reliability. The Bayesian agent learns tool reliability from experience and uses value-of-information calculations to decide when to query, when to cross-verify, and when to abstain. The LangChain agent lets the LLM decide.

Running experiments

# Run tests
uv run pytest -v

# Run all experiments (stationary + drift + ablation)
uv run python -m experiments.run_full_comparison

# Or run individually
uv run python -m experiments.run_stationary --seeds 20
uv run python -m experiments.run_drift --seeds 20
uv run python -m experiments.run_ablation --seeds 20

LangChain agents require a local Ollama instance with llama3.1 (default). Set CREDENCE_LLM_PROVIDER=openai or CREDENCE_LLM_PROVIDER=anthropic for API-based models.

Key Results

Agent Score Accuracy Tools/Q
oracle +188.2 70.6% 1.08
bayesian +112.6 59.6% 0.99
langchain_react -7.4 64.0% 3.22
langchain_enhanced -68.2 66.0% 3.94

The Bayesian agent outscores LangChain by 120 points despite lower accuracy — it queries ~1 tool per question instead of ~3.2, and strategically abstains on low-confidence questions. Enhanced prompting makes LangChain worse by triggering more tool calls without proportional accuracy gains.

See results/RESULTS.md for full results across all three experiments (stationary, drift, ablation).

Project Structure

credence/
├── credence/                    # Facade package — public API re-exports
│   └── __init__.py
├── src/
│   ├── inference/               # Domain-agnostic Bayesian inference layer
│   │   ├── beta_posterior.py    # Beta-Bernoulli reliability tracking
│   │   ├── voi.py               # Value of information, ScoringRule, ToolConfig
│   │   └── decision.py          # EU-based decision logic
│   ├── agents/
│   │   ├── bayesian_agent.py    # Domain-agnostic Bayesian agent
│   │   ├── common.py            # Shared agent interface
│   │   ├── baselines.py         # Random, all-tools, oracle agents
│   │   ├── langchain_agent.py   # Standard LangChain ReAct agent
│   │   └── langchain_enhanced.py # LangChain with best-effort prompting
│   ├── environment/             # Benchmark-specific: simulated tools and questions
│   │   ├── benchmark.py         # The benchmark harness
│   │   ├── tools.py             # Simulated tools with known reliability
│   │   ├── questions.py         # Question bank with ground truth
│   │   └── categories.py        # Category definitions, make_keyword_category_infer_fn
│   ├── analysis/
│   │   ├── metrics.py           # Score, calibration, cost metrics
│   │   └── visualisation.py     # Plots and dashboards
│   └── utils/
│       └── logging.py           # Structured logging for analysis
├── tests/
├── experiments/
│   ├── run_stationary.py        # Main experiment: stationary reliabilities
│   ├── run_drift.py             # Extension: tool reliability drift
│   └── run_ablation.py          # Ablation studies
├── results/                     # Generated plots and data
└── pyproject.toml               # Core deps vs [benchmark] vs [dev] extras

Design Principles

  1. Everything is expected utility maximisation — no heuristics
  2. No hacks — if it doesn't work, fix the model
  3. LLM outputs are data — with quantified uncertainty
  4. The benchmark must be fair — LangChain gets every advantage
  5. Be honest about parameters — every number is justified

See CLAUDE.md for architecture and development guidelines. See SPEC.md for the full mathematical specification.

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

credence_agents-0.2.0.tar.gz (62.1 kB view details)

Uploaded Source

Built Distribution

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

credence_agents-0.2.0-py3-none-any.whl (47.8 kB view details)

Uploaded Python 3

File details

Details for the file credence_agents-0.2.0.tar.gz.

File metadata

  • Download URL: credence_agents-0.2.0.tar.gz
  • Upload date:
  • Size: 62.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for credence_agents-0.2.0.tar.gz
Algorithm Hash digest
SHA256 55a6b5eb48dbd4ffe36b5ac2ea5c307f2dbdf3954e5d9a02959d8233966a806d
MD5 be2b196df66fa6b88c8d8c7ead40766f
BLAKE2b-256 5745ef71795e9eec63ad592924a7cdc27ace03e797da1029cb69748672dbaf3a

See more details on using hashes here.

File details

Details for the file credence_agents-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: credence_agents-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 47.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for credence_agents-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f8d008f78ca3c314805dbf86550f55c2568f16d3ef8f1e599871717c73b8883b
MD5 50949e5c8e226b02fc5e084752c5dce9
BLAKE2b-256 6566efa57ba8835b1d75197a2ba67e86a4cd69340ca5a71c90a360074130ec9e

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