Skip to main content

llm_cascade/models/
response.rs

1//! LLM response types.
2
3use serde::{Deserialize, Serialize};
4
5/// A block of content in an LLM response.
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
7#[serde(tag = "type", rename_all = "snake_case")]
8pub enum ContentBlock {
9    /// Plain text output.
10    Text {
11        /// The text content.
12        text: String,
13    },
14    /// A tool call requested by the model.
15    ToolCall {
16        /// Unique identifier for this tool call.
17        id: String,
18        /// The function name to invoke.
19        name: String,
20        /// JSON-encoded function arguments.
21        arguments: String,
22    },
23}
24
25impl ContentBlock {
26    /// Creates a text content block.
27    pub fn text(text: impl Into<String>) -> Self {
28        ContentBlock::Text { text: text.into() }
29    }
30
31    /// Creates a tool call content block.
32    pub fn tool_call(
33        id: impl Into<String>,
34        name: impl Into<String>,
35        arguments: impl Into<String>,
36    ) -> Self {
37        ContentBlock::ToolCall {
38            id: id.into(),
39            name: name.into(),
40            arguments: arguments.into(),
41        }
42    }
43
44    /// Returns the text content if this is a `Text` block.
45    pub fn as_text(&self) -> Option<&str> {
46        match self {
47            ContentBlock::Text { text } => Some(text),
48            _ => None,
49        }
50    }
51}
52
53/// The full response from an LLM provider.
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct LlmResponse {
56    /// Ordered content blocks (text, tool calls, etc.).
57    pub content: Vec<ContentBlock>,
58    /// Number of input tokens consumed, if reported by the provider.
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub input_tokens: Option<u32>,
61    /// Number of output tokens generated, if reported by the provider.
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub output_tokens: Option<u32>,
64    /// The model identifier returned by the provider.
65    pub model: String,
66}
67
68impl LlmResponse {
69    /// Concatenates all text blocks into a single string.
70    pub fn text_only(&self) -> String {
71        self.content
72            .iter()
73            .filter_map(|b| b.as_text())
74            .collect::<Vec<_>>()
75            .join("")
76    }
77}