Skip to main content

Cambium

Cost discipline and bounded agency for LLM call sites — the deterministic spine decides what to ask, the model only answers.

PyPI Python License: Apache-2.0

What it is

Cambium is the cost-discipline / bounded-agent layer that sits in front of your model calls. Instead of handing an LLM every decision, it routes work through the cheapest path that can answer it and only pays for the model when nothing cheaper will do. Three deterministic, pure-Python capabilities anchor the public surface:

  • cambium.distill — pre-call payload minimization. Decide whether a payload even needs the model (assemble / pass / condense / summarize), shrink oversized payloads deterministically, and record what every call cost via a CostLedger.
  • cambium.resolve — a cost-tiered resolution ladder. Try resolvers in cost order (deterministic → statistical → generative) and stop at the first one confident enough; the expensive generative tier is a budget-gated last resort.
  • cambium.adapt — the feedback substrate for outcome-driven learning: record predictions, observe real outcomes, score them, and attribute credit/blame across the features and strategies that produced them.

Three further deterministic capabilities carry accountability — not "what did we decide" but "at what epistemic strength, and what could we not decide":

  • cambium.epistemics — every claim is typed at construction (theorem / identification / estimate / debt) and a per-profile debt ledger records, machine-readably, what the engine does not know and the evidence that would resolve it.
  • cambium.anchoring — models a conversation as progressive anchoring of a distribution over user intents, with a monotone commitment fraction and a regime read (exploring / deliberating / drifting). Pure, replayable, shadow-safe.
  • cambium.conjunction — eval discipline: score how many independent, zero-tuned predictions one shared config satisfies at once, and flag per-segment parameters that are fitted on too little data to be falsifiable.

Every one of these is deterministic, dependency-light, and replayable — no model call, no RNG, no wall clock — so each result is exactly reproducible from its inputs. See The science for the grounding.

The package import name is cambium; the PyPI distribution is cambium-ai.

Install

pip install cambium-ai

The core (distill / resolve / adapt) has no LLM dependency. Live generative clients are optional extras:

pip install "cambium-ai[claude]"   # live Anthropic client
pip install "cambium-ai[gemini]"   # live Gemini generator

cambium.distill — pre-call payload minimization + cost ledger

prepare runs the full routing pipeline and hands back a ready-to-send payload plus the accounting the ledger needs. Route.ASSEMBLE means no model call at all.

from cambium.distill import prepare, Route, CostLedger

prepared = prepare(task_output, budget_tokens=2000)
ledger = CostLedger(job_id="research-run")

if prepared.route is Route.ASSEMBLE:
    answer = format_table(task_output)                 # deterministic, no model
    ledger.record_avoided(label="summary", route="assemble",
                          tokens_saved=prepared.tokens_saved)
else:
    response = claude.call(prompt_with(prepared.content))   # your model call
    ledger.record(label="summary", model="claude-3-5-haiku",
                  input_tokens=response.input_tokens,
                  output_tokens=response.output_tokens,
                  tier="generative", tokens_saved=prepared.tokens_saved)

report = ledger.report
report.within_budget(max_cost_usd=0.05)   # cost-regression gate

estimate_tokens(content) and condense(content, max_tokens=...) are also public if you want the pieces directly.

cambium.resolve — cost-tiered resolution ladder

Implement a Resolver per tier and let resolve climb only as far as it must. The generative tier is skipped once the ledger is over budget.

from cambium.resolve import Tier, Resolution, resolve
from cambium.distill import CostLedger

class ExactMatch:
    tier = Tier.DETERMINISTIC
    name = "exact_match"
    def resolve(self, request):
        hit = lookup(request)
        if hit is None:
            return None
        return Resolution(value=hit, confidence=1.0, tier=self.tier)

ledger = CostLedger()
result = resolve(
    request,
    [ExactMatch(), embedding_resolver, llm_resolver],
    ledger=ledger,
    threshold=0.8,
    max_cost_usd=0.05,   # gates the generative tier
)

resolve returns the first resolution at/above threshold, else the best below-threshold one, else None. ResolverRegistry is available for grouping resolvers by decision type.

cambium.adapt — outcome-driven feedback substrate

Record predictions, feed back real outcomes, and mature them into scored attributions that a reweighting layer can consume.

from cambium.adapt import (
    PredictionRecord, OutcomeRecord, InMemoryPredictionLedger, mature,
)

led = InMemoryPredictionLedger()
led.record_prediction(PredictionRecord(
    id="p1", subject="AAPL", strategy="momentum",
    features={"rsi": 0.7, "trend": 0.3}, predicted=1.0, baseline=0.0,
))
led.record_outcome(OutcomeRecord(prediction_id="p1", actual=1.0))

scores = mature(led)   # [PredictionScore(accuracy=1.0, attributions={...})]

Weights / update / aggregate and predict_from_attributes / blend_strategies / best_strategy close the loop for the reweighting phase.

cambium.epistemics — typed claims + a debt ledger

Provenance stops being "here is what we decided" and becomes "here is what we decided, at what epistemic strength, and here is the itemized list of what we could not decide and why." Every claim carries a mandatory epistemic type — an untyped claim cannot be constructed — and open questions are registered as resolvable debts.

from cambium.epistemics import (
    EpistemicType, TypedClaim, InMemoryEpistemicLedger, evidence_debts,
)

ledger = InMemoryEpistemicLedger()

# Typed at construction: a bounded numeric claim with stated uncertainty.
ledger.record_claim(TypedClaim.build(
    epistemic_type=EpistemicType.ESTIMATE,
    user_id_hash="u1", domain="finance",
    subject="risk_tolerance", value=0.4, uncertainty=0.25,
))

# Register what the engine does NOT know: asserted dimensions the evidence
# does not actually support become debts, each naming its blocker.
evidence_debts(identity, scores, at=window_end, min_events=3, store=ledger)
for debt in ledger.open_debts():
    print(debt.subject, "→", debt.blocker)   # ... "only 1 of 3 events cite it"

Debts are append-only and immutable — resolved only by a new ResolutionEvent that references them, so the full lineage (opened → evidence arrived → resolved) is always queryable. claims_from_score / claims_from_insight type existing spine outputs without mutating them.

cambium.anchoring — progressive-anchoring conversation model

A conversation is modeled as a live distribution over user intents that contracts as the user commits. Each event is classified by anchoring power (a hedge anchors almost nothing; an executed trade anchors hard), and the tracker emits a monotone commitment fraction plus a provisional regime label.

from cambium.anchoring import (
    IntentDistribution, AnchoringEvent, AnchoringKind, AnchoringTracker,
)

tracker = AnchoringTracker(IntentDistribution.uniform(("save", "invest", "spend")))

for i, kind in enumerate((AnchoringKind.HEDGE,
                          AnchoringKind.STATEMENT,
                          AnchoringKind.EXECUTED_ACTION)):
    snap = tracker.record(
        AnchoringEvent(event_id=f"e{i}", kind=kind, target_intent="invest")
    )
    print(snap.commitment_fraction, snap.top_intent, snap.regime.regime.value)
    # commitment_fraction is monotone non-decreasing across the run, by construction

The regime classifier ships provisional (estimate-typed, dormant) until an eval harness validates its thresholds; the state tracker is safe to run in shadow with zero behavior change. claims_from_snapshot feeds the anchoring signal into the epistemic ledger at its honest strength (estimate, never fact).

cambium.conjunction — conjunction eval discipline

Report not one averaged metric but how many independent, zero-tuned predictions the single shared config gets right simultaneously — and refuse per-segment parameters that overfit their own calibration data.

from cambium.conjunction import (
    Prediction, score_conjunction, conjunction_regression_gate,
    SegmentFit, lint_segment_fits,
)

report = score_conjunction([
    Prediction(name="calibration_ece",     passed=True),
    Prediction(name="direction_agreement", passed=True),
    Prediction(name="judge_min",           passed=False),
])
report.conjunction_score          # 0.667 — two of three, one config, zero tuning

# CI gate: fail a change that regresses any conjunct the baseline got right.
conjunction_regression_gate(baseline_report, report)

# Linter: 3 parameters fitted on 3 examples is a restatement, not a fit.
lint_segment_fits([SegmentFit(segment="cohort_a", num_parameters=3,
                              num_calibration_examples=3,
                              beats_shared_on_holdout=True)])   # → flagged circular

The science

These capabilities emerged from translating an interpretive framework into platform mechanics, but each stands on established, checkable ground — not metaphor. What follows is the actual math the code runs.

Epistemic typing. Claims are partitioned by how they are known, forming a strength ordering: theorem (deductively recomputable from config + inputs) → identification (a model-asserted mapping) → estimate (a bounded numeric claim with explicit uncertainty) → debt (a known-unknown with a named blocker and a declared resolution condition). The debt ledger is an explicit, machine-readable representation of the system's known-unknowns — the epistemic complement to its outputs. The type is required at construction, so the boundary between what was derived and what was asserted can never silently blur.

Anchoring as entropy contraction. The unanchored state is a distribution p over intents; its uncertainty is the Shannon entropy H(p) = -Σ pᵢ ln pᵢ. An anchoring event applies an exponential tilt — a tempered pseudo-observation:

targeted event → pᵢ  ∝  pᵢ · exp(w·κ·[i = target])
untargeted     → pᵢ  ∝  pᵢ^(1 + w·κ)          (tempering toward the current mode)

where w ∈ [0,1] is the event's anchoring weight and κ a single shared sharpness constant. This is standard exponential-family / tempered-Bayesian updating; the "superposition → definite outcome" language is the interpretive metaphor, but the operator is closed-form and deterministic.

Commitment fraction — monotone by construction. Separately from where the intent mass sits, we track how much has been committed. Each event commits a wₙ fraction of the remaining unanchored mass:

Uₙ = Uₙ₋₁ · (1 − wₙ),   U₀ = 1        (unanchored mass)
Cₙ = 1 − Uₙ                            (commitment fraction)

Because every wₙ ∈ [0,1], each factor is in [0,1], so Uₙ is non-increasing and Cₙ is monotone non-decreasing — a guarantee that holds for any event sequence, proven by construction rather than clamped after the fact.

Conjunction over parsimony. A single averaged score hides compensating errors. The conjunction score instead counts how many independent, zero-tuned predictions hold at once — jointly passing N independent checks is a multiplicatively stronger claim than any one metric average, so regression gates key off it. The circularity linter enforces the parsimony discipline behind it: a per-segment parameter set fitted on comparably-sized calibration data (k parameters to k data points) can only restate its inputs — it is unfalsifiable. The linter requires a minimum data-per-parameter ratio and a held-out improvement over the shared default before per-segment tuning is admitted (an Occam / model-selection constraint applied to config).

Every formula above is exercised by the test suite and computed with no model call, so the numbers are exactly reproducible from their inputs.

License

Apache-2.0. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cambium_ai-0.3.0.tar.gz (143.6 kB view details)

Uploaded Source

Built Distribution

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

cambium_ai-0.3.0-py3-none-any.whl (144.3 kB view details)

Uploaded Python 3

File details

Details for the file cambium_ai-0.3.0.tar.gz.

File metadata

  • Download URL: cambium_ai-0.3.0.tar.gz
  • Upload date:
  • Size: 143.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.14 Linux/6.17.0-1020-azure

File hashes

Hashes for cambium_ai-0.3.0.tar.gz
Algorithm Hash digest
SHA256 4dc64180ca54e12b99ed26f927c2a3a7bc98a171ce31102a530d79eaa0d70706
MD5 a35a8b5f55bfbe05ac391074671257c0
BLAKE2b-256 5fb2833546ce79abfb29ae65662fbfa0d111ff25b015faa430e8e6fb29b3a060

See more details on using hashes here.

File details

Details for the file cambium_ai-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: cambium_ai-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 144.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.14 Linux/6.17.0-1020-azure

File hashes

Hashes for cambium_ai-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7df05573c7e23521e671d6596f8c975cc53522f0a8752426fd0f43a47fba8973
MD5 58f399fa55a480e146b6bd3596ce2905
BLAKE2b-256 1b06bdc08ac49d04384ac6f4304f3ad5b6ae3fb803b6b3ec33e145a640ccda44

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