Skip to main content

key_token/
response.rs

1use serde::{Deserialize, Serialize};
2
3/// OpenAI 兼容的流式响应块
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct ChatCompletionChunk {
6    pub id: String,
7    pub object: String,
8    pub created: i64,
9    pub model: String,
10    pub choices: Vec<Choice>,
11}
12
13impl ChatCompletionChunk {
14    pub fn new(id: impl Into<String>, model: impl Into<String>) -> Self {
15        Self {
16            id: id.into(),
17            object: "chat.completion.chunk".to_string(),
18            created: chrono::Utc::now().timestamp(),
19            model: model.into(),
20            choices: Vec::new(),
21        }
22    }
23
24    pub fn with_choice(mut self, choice: Choice) -> Self {
25        self.choices.push(choice);
26        self
27    }
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct Choice {
32    pub index: u32,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub delta: Option<MessageDelta>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub finish_reason: Option<String>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct MessageDelta {
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub role: Option<String>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub content: Option<String>,
45}
46
47impl MessageDelta {
48    pub fn content(content: impl Into<String>) -> Self {
49        Self {
50            role: None,
51            content: Some(content.into()),
52        }
53    }
54
55    pub fn with_role(mut self, role: impl Into<String>) -> Self {
56        self.role = Some(role.into());
57        self
58    }
59}
60
61/// OpenAI 兼容的非流式响应
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct ChatCompletionResponse {
64    pub id: String,
65    pub object: String,
66    pub created: i64,
67    pub model: String,
68    pub choices: Vec<CompletionChoice>,
69    pub usage: Usage,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct CompletionChoice {
74    pub index: u32,
75    pub message: MessageContent,
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub finish_reason: Option<String>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct MessageContent {
82    pub role: String,
83    pub content: String,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize, Default)]
87pub struct Usage {
88    pub prompt_tokens: u32,
89    pub completion_tokens: u32,
90    pub total_tokens: u32,
91}
92
93/// 模型信息
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ModelInfo {
96    pub id: String,
97    pub object: String,
98    pub created: i64,
99    pub owned_by: String,
100}
101
102impl ModelInfo {
103    pub fn new(id: impl Into<String>, owned_by: impl Into<String>) -> Self {
104        Self {
105            id: id.into(),
106            object: "model".to_string(),
107            created: chrono::Utc::now().timestamp(),
108            owned_by: owned_by.into(),
109        }
110    }
111}
112
113/// 模型列表响应
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct ModelListResponse {
116    pub object: String,
117    pub data: Vec<ModelInfo>,
118}
119
120impl ModelListResponse {
121    pub fn new(models: Vec<ModelInfo>) -> Self {
122        Self {
123            object: "list".to_string(),
124            data: models,
125        }
126    }
127}
128
129/// 错误响应
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct ErrorResponse {
132    pub error: ErrorDetail,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct ErrorDetail {
137    pub message: String,
138    #[serde(rename = "type")]
139    pub error_type: String,
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub param: Option<String>,
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub code: Option<String>,
144}
145
146impl ErrorResponse {
147    pub fn new(message: impl Into<String>, error_type: impl Into<String>) -> Self {
148        Self {
149            error: ErrorDetail {
150                message: message.into(),
151                error_type: error_type.into(),
152                param: None,
153                code: None,
154            },
155        }
156    }
157
158    pub fn with_code(mut self, code: impl Into<String>) -> Self {
159        self.error.code = Some(code.into());
160        self
161    }
162}