pub struct ContextBudget {
pub max_tokens: u64,
pub share: f32,
}Expand description
How much of a request the observation log may occupy.
The half of budgeting that TaskContract::with_token_budget is not:
that bounds what a whole run may spend, this bounds what any one request
carries of what the run has already observed. Without it a long workspace
run re-sends its entire history every turn and the cost of turn n grows
with n.
use io_harness::ContextBudget;
let budget = ContextBudget::default();
assert_eq!(budget.max_tokens, 24_000);
assert_eq!(budget.share, 0.5);
// With no run token budget, the ceiling is `max_tokens` flat.
assert_eq!(budget.effective_tokens(None), 24_000);
// With one, the prompt takes `share` of what is *left* — so a run running
// low stops spending what remains on re-sending history and leaves it for
// doing the work.
assert_eq!(budget.effective_tokens(Some(100_000)), 24_000); // capped by max_tokens
assert_eq!(budget.effective_tokens(Some(20_000)), 10_000); // half of the remainder
assert_eq!(budget.effective_tokens(Some(1_000)), 2_000); // floored, never zeroThat last line is the floor: a prompt too small to carry one observation is a turn the agent cannot act on, so the final turns still get a usable request even when it exceeds what is nominally left.
Tighten it for a model with a small window, or for a run whose observations are large:
use io_harness::{ContextBudget, TaskContract, Verification};
let contract = TaskContract::workspace(
"make the failing test pass",
"/path/to/repo",
Verification::WorkspaceFileContains { file: "OK".into(), needle: "ok".into() },
)
.with_token_budget(200_000)
.with_context_budget(ContextBudget { max_tokens: 8_000, share: 0.25 });Fields§
§max_tokens: u64Absolute per-request ceiling for the assembled prompt.
Share of the token budget still unspent that the prompt may use.
Implementations§
Source§impl ContextBudget
impl ContextBudget
Sourcepub fn effective_tokens(&self, remaining_budget: Option<u64>) -> u64
pub fn effective_tokens(&self, remaining_budget: Option<u64>) -> u64
The ceiling for this turn’s assembled section.
With no run token budget it is max_tokens
flat. With one, it is the configured share of what is left, so a run
running out of budget spends less of it on re-sent history — floored at
2000 tokens so the last turns still send a usable prompt, and never
above max_tokens.
Trait Implementations§
Source§impl Clone for ContextBudget
impl Clone for ContextBudget
Source§fn clone(&self) -> ContextBudget
fn clone(&self) -> ContextBudget
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for ContextBudget
Source§impl Debug for ContextBudget
impl Debug for ContextBudget
Source§impl Default for ContextBudget
impl Default for ContextBudget
Source§impl PartialEq for ContextBudget
impl PartialEq for ContextBudget
impl StructuralPartialEq for ContextBudget
Auto Trait Implementations§
impl Freeze for ContextBudget
impl RefUnwindSafe for ContextBudget
impl Send for ContextBudget
impl Sync for ContextBudget
impl Unpin for ContextBudget
impl UnsafeUnpin for ContextBudget
impl UnwindSafe for ContextBudget
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().impl<T> Scalar for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.