openai_interface/chat/response/
no_streaming.rs1use serde::Deserialize;
2
3use crate::errors::ResponseError;
4
5#[derive(Debug, Deserialize)]
6pub struct Completion {
7 pub id: String,
8 pub choices: Vec<ResponseChoice>,
9 pub created: u64,
10 pub model: String,
11 pub system_fingerprint: String,
12 pub object: String,
13 pub usage: CompletionUsage,
14}
15
16#[derive(Debug, Deserialize)]
17pub struct ResponseChoice {
18 pub finish_reason: FinishReason,
19 pub index: usize,
20 pub message: ResponseMessage,
21 pub logprobs: Option<ResponseLogprobs>,
22}
23
24#[derive(Debug, Deserialize, PartialEq)]
25#[serde(rename_all = "snake_case")]
26pub enum FinishReason {
27 Length,
28 Stop,
29 ContentFilter,
30 InsufficientSystemResource,
31}
32
33#[derive(Debug, Deserialize)]
34pub struct ResponseMessage {
35 pub role: ResponseRole,
37 pub content: Option<String>,
38 pub reasoning_content: Option<String>,
39 pub tool_calls: Option<String>,
41}
42
43#[derive(Debug, Deserialize)]
44#[serde(rename_all = "snake_case")]
45pub enum ResponseRole {
46 User,
47 Assistant,
48 System,
49 Tool,
50}
51
52#[derive(Debug, Deserialize)]
53pub struct ResponseLogprobs {
54 pub content: Vec<LogProb>,
55 pub reasoning_content: Vec<LogProb>,
56}
57
58#[derive(Debug, Deserialize)]
59pub struct LogProb {
60 pub token: String,
61 pub logprob: f32,
62 pub bytes: Option<Vec<u8>>,
63 pub top_logprobs: Vec<TopLogprob>,
64}
65
66#[derive(Debug, Deserialize)]
67pub struct TopLogprob {
68 pub token: String,
69 pub logprob: f32,
70 pub bytes: Option<Vec<u8>>,
71}
72
73#[derive(Debug, Deserialize)]
74pub struct CompletionUsage {
75 pub completion_tokens: usize,
76 pub prompt_tokens: usize,
77
78 pub prompt_cache_hit_tokens: Option<usize>,
80 pub prompt_cache_miss_tokens: Option<usize>,
81
82 pub total_tokens: usize,
83 pub completion_tokens_details: Option<CompletionTokensDetails>,
84}
85
86#[derive(Debug, Deserialize)]
87pub struct CompletionTokensDetails {
88 pub reasoning_tokens: usize,
89}
90
91impl Completion {
92 pub fn parse_string(content: &str) -> Result<Self, crate::errors::ResponseError> {
93 let parse_result: Result<Completion, _> = serde_json::from_str(content)
94 .map_err(|e| ResponseError::DeserializationError(e.to_string()));
95 parse_result
96 }
97}
98
99#[cfg(test)]
100mod test {
101
102 #[test]
103 fn no_streaming_example_deepseek() {
104 let json = r#"{
105 "id": "30f6413a-a827-4cf3-9898-f13a8634b798",
106 "object": "chat.completion",
107 "created": 1757944111,
108 "model": "deepseek-chat",
109 "choices": [
110 {
111 "index": 0,
112 "message": {
113 "role": "assistant",
114 "content": "Hello! How can I help you today? 😊"
115 },
116 "logprobs": null,
117 "finish_reason": "stop"
118 }
119 ],
120 "usage": {
121 "prompt_tokens": 10,
122 "completion_tokens": 11,
123 "total_tokens": 21,
124 "prompt_tokens_details": {
125 "cached_tokens": 0
126 },
127 "prompt_cache_hit_tokens": 0,
128 "prompt_cache_miss_tokens": 10
129 },
130 "system_fingerprint": "fp_08f168e49b_prod0820_fp8_kvcache"
131 }"#;
132
133 let parsed = super::Completion::parse_string(json);
134 match parsed {
135 Ok(_) => {}
136 Err(e) => {
137 panic!("Failed to deserialize: {}", e);
138 }
139 }
140 }
141}