1use crate::types::Choice;
2use serde::{Deserialize, Serialize};
3
4#[doc(alias = "token_usage")]
10#[doc(alias = "usage_info")]
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Usage {
13 pub prompt_tokens: u32,
14 pub completion_tokens: u32,
15 pub total_tokens: u32,
16}
17
18#[doc(alias = "usage_status")]
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
21pub enum UsageStatus {
22 #[serde(rename = "finalized")]
24 Finalized,
25 #[serde(rename = "estimated")]
27 Estimated,
28 #[serde(rename = "pending")]
30 Pending,
31 #[serde(rename = "unsupported")]
33 Unsupported,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct ChatCompletionResponse {
38 pub id: String,
39 pub object: String,
40 pub created: u64,
41 pub model: String,
42 pub choices: Vec<Choice>,
43 pub usage: Usage,
44 pub usage_status: UsageStatus,
46}
47
48impl ChatCompletionResponse {
49 pub fn first_text(&self) -> Result<&str, crate::types::AiLibError> {
52 let choice = self.choices.first().ok_or_else(|| {
53 crate::types::AiLibError::InvalidModelResponse("empty choices".into())
54 })?;
55 match &choice.message.content {
56 crate::types::common::Content::Text(t) => Ok(t.as_str()),
57 other => Err(crate::types::AiLibError::InvalidModelResponse(format!(
58 "expected text content, got {:?}",
59 other
60 ))),
61 }
62 }
63}