1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use serde::{Deserialize, Serialize};
/// Token consumption reported by a single LLM generation call.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TokenUsage {
/// Tokens consumed by the prompt (input side).
pub prompt_tokens: u32,
/// Tokens produced in the completion (output side).
pub completion_tokens: u32,
/// `prompt_tokens + completion_tokens`.
pub total_tokens: u32,
}
impl TokenUsage {
/// Combine two [`TokenUsage`] records by summing each field.
///
/// Useful when aggregating usage across multiple LLM calls in one chain run.
///
/// # Example
///
/// ```rust
/// use rune_chain_core::TokenUsage;
///
/// let a = TokenUsage { prompt_tokens: 10, completion_tokens: 20, total_tokens: 30 };
/// let b = TokenUsage { prompt_tokens: 5, completion_tokens: 8, total_tokens: 13 };
/// let combined = a.combine(&b);
/// assert_eq!(combined.total_tokens, 43);
/// ```
pub fn combine(&self, other: &TokenUsage) -> TokenUsage {
TokenUsage {
prompt_tokens: self.prompt_tokens + other.prompt_tokens,
completion_tokens: self.completion_tokens + other.completion_tokens,
total_tokens: self.total_tokens + other.total_tokens,
}
}
}
/// The result of a single LLM generation call.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GenerateResult {
/// The text produced by the model.
pub generation: String,
/// Token usage, if reported by the provider.
pub tokens: Option<TokenUsage>,
}
impl GenerateResult {
/// Create a [`GenerateResult`] with just the generated text and no token data.
///
/// # Example
///
/// ```rust
/// use rune_chain_core::GenerateResult;
///
/// let result = GenerateResult::from_text("4");
/// assert_eq!(result.generation, "4");
/// assert!(result.tokens.is_none());
/// ```
pub fn from_text(text: impl Into<String>) -> Self {
Self {
generation: text.into(),
tokens: None,
}
}
}