walrus_core/model/
response.rs1use crate::model::{Message, Role, tool::ToolCall};
4use compact_str::CompactString;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Deserialize, Default)]
9pub struct CompletionMeta {
10 pub id: CompactString,
12
13 pub object: CompactString,
15
16 pub created: u64,
18
19 pub model: CompactString,
21
22 pub system_fingerprint: Option<CompactString>,
24}
25
26#[derive(Debug, Clone, Deserialize, Default)]
30pub struct Delta {
31 pub role: Option<Role>,
33
34 pub content: Option<String>,
36
37 pub reasoning_content: Option<String>,
39
40 pub tool_calls: Option<Vec<ToolCall>>,
42}
43
44#[derive(Debug, Clone, Deserialize)]
46pub struct Response {
47 #[serde(flatten)]
49 pub meta: CompletionMeta,
50
51 pub choices: Vec<Choice>,
53
54 pub usage: Usage,
56}
57
58impl Response {
59 pub fn message(&self) -> Option<Message> {
60 let choice = self.choices.first()?;
61 Some(Message::assistant(
62 choice.delta.content.clone().unwrap_or_default(),
63 choice.delta.reasoning_content.clone(),
64 choice.delta.tool_calls.as_deref(),
65 ))
66 }
67
68 pub fn content(&self) -> Option<&String> {
70 self.choices
71 .first()
72 .and_then(|choice| choice.delta.content.as_ref())
73 }
74
75 pub fn reasoning(&self) -> Option<&String> {
77 self.choices
78 .first()
79 .and_then(|choice| choice.delta.reasoning_content.as_ref())
80 }
81
82 pub fn tool_calls(&self) -> Option<&[ToolCall]> {
84 self.choices
85 .first()
86 .and_then(|choice| choice.delta.tool_calls.as_deref())
87 }
88
89 pub fn reason(&self) -> Option<&FinishReason> {
91 self.choices
92 .first()
93 .and_then(|choice| choice.finish_reason.as_ref())
94 }
95}
96
97#[derive(Debug, Clone, Deserialize, Default)]
99pub struct Choice {
100 pub index: u32,
102
103 #[serde(alias = "message")]
105 pub delta: Delta,
106
107 pub finish_reason: Option<FinishReason>,
109
110 pub logprobs: Option<LogProbs>,
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize)]
116#[serde(rename_all = "snake_case")]
117pub enum FinishReason {
118 Stop,
120
121 Length,
123
124 ContentFilter,
126
127 ToolCalls,
129
130 InsufficientSystemResource,
132}
133
134#[derive(Debug, Clone, Deserialize)]
136pub struct Usage {
137 pub prompt_tokens: u32,
139
140 pub completion_tokens: u32,
142
143 pub total_tokens: u32,
145
146 pub prompt_cache_hit_tokens: Option<u32>,
148
149 pub prompt_cache_miss_tokens: Option<u32>,
151
152 pub completion_tokens_details: Option<CompletionTokensDetails>,
154}
155
156#[derive(Debug, Clone, Deserialize)]
158pub struct CompletionTokensDetails {
159 pub reasoning_tokens: Option<u32>,
161}
162
163#[derive(Debug, Clone, Deserialize)]
165pub struct LogProbs {
166 pub content: Option<Vec<LogProb>>,
168}
169
170#[derive(Debug, Clone, Deserialize, Serialize)]
172pub struct LogProb {
173 pub token: String,
175
176 pub logprob: f64,
178
179 #[serde(skip_serializing_if = "Option::is_none")]
181 pub bytes: Option<Vec<u8>>,
182
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub top_logprobs: Option<Vec<TopLogProb>>,
186}
187
188#[derive(Debug, Clone, Deserialize, Serialize)]
190pub struct TopLogProb {
191 pub token: String,
193
194 pub logprob: f64,
196
197 #[serde(skip_serializing_if = "Option::is_none")]
199 pub bytes: Option<Vec<u8>>,
200}