Skip to main content

Usage

Struct Usage 

Source
pub struct Usage { /* private fields */ }
Expand description

Thread-safe request and token counters.

A Client fills its own Usage from the usage object of every successful reply and counts each retry. The counters are atomic, so the totals can be read while requests are in flight; they are then a snapshot, not a transaction.

Usage::record and Usage::record_retry are public so that a caller who talks to another provider through the same code path can keep the same accounting.

Implementations§

Source§

impl Usage

Source

pub fn record(&self, input_tokens: u64, output_tokens: u64)

One completed request and the tokens it used.

Source

pub fn record_retry(&self)

One attempt that had to be repeated. A request that is retried twice before it succeeds counts as one request and two retries.

Source

pub fn requests(&self) -> u64

Requests that were answered.

Examples found in repository?
examples/ask.rs (line 76)
20fn main() -> Result<(), Error> {
21    let client = Client::from_env(Config::default())?;
22
23    let ticket = Ticket {
24        customer_plan: "business",
25        message: "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. \
26                  I'm losing sales. Please help ASAP.",
27    };
28    let questions = Questions::new()
29        .with(
30            "department",
31            Choice::new(
32                "Which team should handle the `message`?",
33                [
34                    ("billing", "Payment or subscription issues"),
35                    ("technical", "Bugs or integration problems"),
36                    ("sales", "Pricing or account questions"),
37                ],
38            ),
39        )
40        .with(
41            "frustration",
42            Score::new(
43                "How frustrated the customer appears",
44                ["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"],
45            ),
46        )
47        .with("is_urgent", Noul::new("The message conveys urgency or time-sensitivity"));
48
49    let response = match client.ask(&ticket, &questions) {
50        Ok(response) => response,
51        // Too much state for one request: a real caller would split it and ask again.
52        Err(Error::TokenLimit(message)) => {
53            eprintln!("request too large: {message}");
54            return Ok(());
55        }
56        Err(other) => return Err(other),
57    };
58
59    if let Some(department) = response.choice("department") {
60        println!("department: {} (confidence {:.2})", department.choice, department.confidence);
61        for (option, probability) in &department.probabilities {
62            println!("  {option}: {probability:.2}");
63        }
64    }
65    if let Some(frustration) = response.score("frustration") {
66        println!("frustration: {:.2} of {} (confidence {:.2})", frustration.score, frustration.legend.len() - 1, frustration.confidence);
67    }
68    if let Some(urgent) = response.noul("is_urgent") {
69        println!("urgent: p={:.2}", urgent.noul);
70    }
71
72    let usage = client.usage();
73    println!(
74        "{}: {} request(s), {} retries, {} input tokens, ~${:.6}",
75        response.model,
76        usage.requests(),
77        usage.retries(),
78        usage.input_tokens(),
79        usage.cost_usd()
80    );
81    Ok(())
82}
Source

pub fn retries(&self) -> u64

Attempts that were repeated after a transient failure.

Examples found in repository?
examples/ask.rs (line 77)
20fn main() -> Result<(), Error> {
21    let client = Client::from_env(Config::default())?;
22
23    let ticket = Ticket {
24        customer_plan: "business",
25        message: "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. \
26                  I'm losing sales. Please help ASAP.",
27    };
28    let questions = Questions::new()
29        .with(
30            "department",
31            Choice::new(
32                "Which team should handle the `message`?",
33                [
34                    ("billing", "Payment or subscription issues"),
35                    ("technical", "Bugs or integration problems"),
36                    ("sales", "Pricing or account questions"),
37                ],
38            ),
39        )
40        .with(
41            "frustration",
42            Score::new(
43                "How frustrated the customer appears",
44                ["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"],
45            ),
46        )
47        .with("is_urgent", Noul::new("The message conveys urgency or time-sensitivity"));
48
49    let response = match client.ask(&ticket, &questions) {
50        Ok(response) => response,
51        // Too much state for one request: a real caller would split it and ask again.
52        Err(Error::TokenLimit(message)) => {
53            eprintln!("request too large: {message}");
54            return Ok(());
55        }
56        Err(other) => return Err(other),
57    };
58
59    if let Some(department) = response.choice("department") {
60        println!("department: {} (confidence {:.2})", department.choice, department.confidence);
61        for (option, probability) in &department.probabilities {
62            println!("  {option}: {probability:.2}");
63        }
64    }
65    if let Some(frustration) = response.score("frustration") {
66        println!("frustration: {:.2} of {} (confidence {:.2})", frustration.score, frustration.legend.len() - 1, frustration.confidence);
67    }
68    if let Some(urgent) = response.noul("is_urgent") {
69        println!("urgent: p={:.2}", urgent.noul);
70    }
71
72    let usage = client.usage();
73    println!(
74        "{}: {} request(s), {} retries, {} input tokens, ~${:.6}",
75        response.model,
76        usage.requests(),
77        usage.retries(),
78        usage.input_tokens(),
79        usage.cost_usd()
80    );
81    Ok(())
82}
Source

pub fn input_tokens(&self) -> u64

Input tokens, as reported by the API.

Examples found in repository?
examples/ask.rs (line 78)
20fn main() -> Result<(), Error> {
21    let client = Client::from_env(Config::default())?;
22
23    let ticket = Ticket {
24        customer_plan: "business",
25        message: "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. \
26                  I'm losing sales. Please help ASAP.",
27    };
28    let questions = Questions::new()
29        .with(
30            "department",
31            Choice::new(
32                "Which team should handle the `message`?",
33                [
34                    ("billing", "Payment or subscription issues"),
35                    ("technical", "Bugs or integration problems"),
36                    ("sales", "Pricing or account questions"),
37                ],
38            ),
39        )
40        .with(
41            "frustration",
42            Score::new(
43                "How frustrated the customer appears",
44                ["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"],
45            ),
46        )
47        .with("is_urgent", Noul::new("The message conveys urgency or time-sensitivity"));
48
49    let response = match client.ask(&ticket, &questions) {
50        Ok(response) => response,
51        // Too much state for one request: a real caller would split it and ask again.
52        Err(Error::TokenLimit(message)) => {
53            eprintln!("request too large: {message}");
54            return Ok(());
55        }
56        Err(other) => return Err(other),
57    };
58
59    if let Some(department) = response.choice("department") {
60        println!("department: {} (confidence {:.2})", department.choice, department.confidence);
61        for (option, probability) in &department.probabilities {
62            println!("  {option}: {probability:.2}");
63        }
64    }
65    if let Some(frustration) = response.score("frustration") {
66        println!("frustration: {:.2} of {} (confidence {:.2})", frustration.score, frustration.legend.len() - 1, frustration.confidence);
67    }
68    if let Some(urgent) = response.noul("is_urgent") {
69        println!("urgent: p={:.2}", urgent.noul);
70    }
71
72    let usage = client.usage();
73    println!(
74        "{}: {} request(s), {} retries, {} input tokens, ~${:.6}",
75        response.model,
76        usage.requests(),
77        usage.retries(),
78        usage.input_tokens(),
79        usage.cost_usd()
80    );
81    Ok(())
82}
Source

pub fn output_tokens(&self) -> u64

Output tokens, as reported by the API. Jev reports them, but does not charge for them.

Source

pub fn cost_usd(&self) -> f64

The input tokens at Jev’s list price, USD_PER_INPUT_MTOK. An estimate: the price is a constant in this crate, not something the API reports.

Examples found in repository?
examples/ask.rs (line 79)
20fn main() -> Result<(), Error> {
21    let client = Client::from_env(Config::default())?;
22
23    let ticket = Ticket {
24        customer_plan: "business",
25        message: "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. \
26                  I'm losing sales. Please help ASAP.",
27    };
28    let questions = Questions::new()
29        .with(
30            "department",
31            Choice::new(
32                "Which team should handle the `message`?",
33                [
34                    ("billing", "Payment or subscription issues"),
35                    ("technical", "Bugs or integration problems"),
36                    ("sales", "Pricing or account questions"),
37                ],
38            ),
39        )
40        .with(
41            "frustration",
42            Score::new(
43                "How frustrated the customer appears",
44                ["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"],
45            ),
46        )
47        .with("is_urgent", Noul::new("The message conveys urgency or time-sensitivity"));
48
49    let response = match client.ask(&ticket, &questions) {
50        Ok(response) => response,
51        // Too much state for one request: a real caller would split it and ask again.
52        Err(Error::TokenLimit(message)) => {
53            eprintln!("request too large: {message}");
54            return Ok(());
55        }
56        Err(other) => return Err(other),
57    };
58
59    if let Some(department) = response.choice("department") {
60        println!("department: {} (confidence {:.2})", department.choice, department.confidence);
61        for (option, probability) in &department.probabilities {
62            println!("  {option}: {probability:.2}");
63        }
64    }
65    if let Some(frustration) = response.score("frustration") {
66        println!("frustration: {:.2} of {} (confidence {:.2})", frustration.score, frustration.legend.len() - 1, frustration.confidence);
67    }
68    if let Some(urgent) = response.noul("is_urgent") {
69        println!("urgent: p={:.2}", urgent.noul);
70    }
71
72    let usage = client.usage();
73    println!(
74        "{}: {} request(s), {} retries, {} input tokens, ~${:.6}",
75        response.model,
76        usage.requests(),
77        usage.retries(),
78        usage.input_tokens(),
79        usage.cost_usd()
80    );
81    Ok(())
82}

Trait Implementations§

Source§

impl Debug for Usage

Source§

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

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

impl Default for Usage

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl !Freeze for Usage

§

impl RefUnwindSafe for Usage

§

impl Send for Usage

§

impl Sync for Usage

§

impl Unpin for Usage

§

impl UnsafeUnpin for Usage

§

impl UnwindSafe for Usage

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> 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, 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.