Skip to main content

CostModel

Struct CostModel 

Source
pub struct CostModel {
    pub input: Decimal,
    pub output: Decimal,
    pub cache_read: Decimal,
    pub cache_write: Decimal,
    pub cache_write_long: Option<Decimal>,
    pub context_window: u32,
    pub max_output: u32,
    pub as_of: AsOf,
}
Expand description

What one reasoner charges, and how much it can be given.

§Example

use boundgraph_core::{AsOf, CostModel, TokenUsage};
use rust_decimal::Decimal;

let usd = |s: &str| s.parse::<Decimal>().unwrap();

let model = CostModel::new(
    usd("5.00"),   // input, per million tokens
    usd("25.00"),  // output
    AsOf::new(2026, 6, 24).unwrap(),
)
.with_context_window(1_000_000)
.with_cache_rates(usd("0.50"), usd("6.25"));

// A cached read is a tenth of the uncached rate, and the price says so.
let cold = model.price(&TokenUsage { input: 1_000_000, ..TokenUsage::NONE });
let warm = model.price(&TokenUsage { cache_read: 1_000_000, ..TokenUsage::NONE });
assert_eq!(cold, usd("5.00"));
assert_eq!(warm, usd("0.50"));

Fields§

§input: Decimal

US dollars per million uncached prompt tokens.

§output: Decimal

US dollars per million completion tokens.

§cache_read: Decimal

US dollars per million prompt tokens served from the cache.

Substantially below input — that difference is the whole point of caching, and collapsing the two would hide it.

§cache_write: Decimal

US dollars per million prompt tokens written to the cache.

Above input: a write costs more than not caching at all, which is why a prefix has to be read back at least twice before caching it pays for itself.

§cache_write_long: Option<Decimal>

The same, for a provider’s longer-lived cache tier, if it has one.

§context_window: u32

The largest prompt this model will accept, in tokens.

A ceiling the compiler checks a flow’s declared context against, so “this step asks for more window than the model has” is a build error rather than a run-time refusal.

§max_output: u32

The largest completion it will produce, in tokens.

§as_of: AsOf

The date these figures were correct on.

Implementations§

Source§

impl CostModel

Source

pub fn new(input: Decimal, output: Decimal, as_of: AsOf) -> Self

A model priced per million tokens, with no cache tier.

Cache rates default to the uncached input rate, which is the conservative reading: a provider that has not told us caching is cheaper is priced as though it is not.

Source

pub fn with_cache_rates(self, read: Decimal, write: Decimal) -> Self

Declare the cache tier’s rates.

Source

pub fn with_long_cache_write(self, write: Decimal) -> Self

Declare a longer-lived cache tier’s write rate.

Source

pub fn with_context_window(self, tokens: u32) -> Self

Declare the prompt ceiling.

Source

pub fn with_max_output(self, tokens: u32) -> Self

Declare the completion ceiling.

Source

pub fn price(&self, usage: &TokenUsage) -> Decimal

What a call consuming usage costs, in US dollars.

Exact decimal arithmetic throughout: this figure ends up in the ledger and gets summed across a run, and a rounding error that compounds is worse than no figure at all.

Source

pub fn admits(&self, prompt_tokens: u32) -> bool

Whether a prompt of this size fits.

Source

pub fn is_stale(&self, horizon: AsOf) -> bool

Whether these figures are older than horizon.

Source

pub fn prices_alike(&self, other: &Self) -> bool

Whether two models would price the same call identically.

What a failover has to satisfy: a fallback that charges differently changes the ceiling the flow was compiled against, so the compiler refuses it (US-0604) rather than letting the proved bound quietly stop being true.

Source

pub fn costlier(&self, other: &Self) -> Self

Whichever of two models is more expensive on every rate.

Used to bound a choice the compiler cannot resolve — a ladder or a failover list — by pricing it at its worst case rather than its expected one.

Trait Implementations§

Source§

impl Clone for CostModel

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CostModel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for CostModel

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for CostModel

Source§

impl PartialEq for CostModel

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for CostModel

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for CostModel

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Canonical for T
where T: Serialize + ?Sized,

Source§

fn canonical_bytes(&self) -> Result<Vec<u8>, CanonicalError>

The canonical CBOR encoding of this value.
Source§

fn digest(&self) -> Result<Digest, CanonicalError>

The blake3 digest of this value’s canonical encoding.
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V