batch_mode_batch_schema/
batch_response_content.rs

1// ---------------- [ File: batch-mode-batch-schema/src/batch_response_content.rs ]
2crate::ix!();
3
4#[derive(Builder,Getters,Clone,Debug,Serialize,Deserialize)]
5#[builder(setter(into))]
6#[getset(get="pub")]
7pub struct BatchResponseContent {
8    status_code: u16,
9    request_id:  ResponseRequestId,
10    body:        BatchResponseBody,
11}
12
13impl BatchResponseContent {
14
15    pub fn mock_with_code_and_body(custom_id: &str, code: u16, body: &serde_json::Value) -> Self {
16        BatchResponseContent {
17            status_code: code,
18            request_id:  ResponseRequestId::new(format!("resp_req_{custom_id}")),
19            body:        BatchResponseBody::mock_with_code_and_body(code,body),
20        }
21    }
22
23    pub fn mock_with_code(custom_id: &str, code: u16) -> Self {
24        BatchResponseContent {
25            status_code: code,
26            request_id:  ResponseRequestId::new(format!("req_resp_{}", custom_id)),
27            body:        BatchResponseBody::mock(custom_id, code),
28        }
29    }
30
31    pub fn mock(custom_id: &str) -> Self {
32        BatchResponseContent {
33            status_code: 400,
34            request_id: ResponseRequestId::new(format!("resp_req_{}", custom_id)),
35            body:       BatchResponseBody::mock_error(custom_id),
36        }
37    }
38
39    /// Checks if the response indicates success (status code 200)
40    pub fn is_success(&self) -> bool {
41        self.status_code == 200
42    }
43
44    /// Retrieves the success body if present
45    pub fn success_body(&self) -> Option<&BatchSuccessResponseBody> {
46        match &self.body {
47            BatchResponseBody::Success(body) => Some(body),
48            _ => None,
49        }
50    }
51
52    /// Retrieves the error body if present
53    pub fn error_body(&self) -> Option<&BatchErrorResponseBody> {
54        match &self.body {
55            BatchResponseBody::Error(body) => Some(body),
56            _ => None,
57        }
58    }
59}
60
61#[cfg(test)]
62mod batch_response_content_tests {
63    use super::*;
64    use serde_json::json;
65
66    #[traced_test]
67    fn test_success_response_content() {
68        info!("Starting test: test_success_response_content");
69
70        let json_data = json!({
71            "status_code": 200,
72            "request_id": "req_123",
73            "body": {
74                "id": "chatcmpl-AVW7Z2Dd49g7Zq5eVExww6dlKA8T9",
75                "object": "chat.completion",
76                "created": 1732075005,
77                "model": "gpt-4o-2024-08-06",
78                "choices": [],
79                "usage": {
80                    "prompt_tokens": 40,
81                    "completion_tokens": 360,
82                    "total_tokens": 400
83                },
84                "system_fingerprint": "fp_7f6be3efb0"
85            }
86        });
87
88        let response: BatchResponseContent = serde_json::from_value(json_data).unwrap();
89        pretty_assert_eq!(*response.status_code(), 200);
90        assert!(response.is_success());
91        pretty_assert_eq!(response.request_id().as_str(), "req_123");
92
93        if let Some(body) = response.success_body() {
94            // FIX: compare with Some(&"string".to_string()) for id/model/object
95            pretty_assert_eq!(
96                body.id(),
97                &"chatcmpl-AVW7Z2Dd49g7Zq5eVExww6dlKA8T9".to_string()
98            );
99            pretty_assert_eq!(
100                body.object(),
101                &"chat.completion".to_string()
102            );
103            pretty_assert_eq!(
104                body.model(),
105                &"gpt-4o-2024-08-06".to_string()
106            );
107        } else {
108            panic!("Expected success_body() to be Some(...)");
109        }
110
111        info!("Finished test: test_success_response_content");
112    }
113
114    #[test]
115    fn test_error_response_content() {
116        let json_data = json!({
117            "status_code": 400,
118            "request_id": "req_789",
119            "body": {
120                "error": {
121                    "message": "Invalid request",
122                    "type": "invalid_request_error",
123                    "param": "prompt",
124                    "code": "invalid_prompt"
125                }
126            }
127        });
128
129        let response: BatchResponseContent = serde_json::from_value(json_data).unwrap();
130        pretty_assert_eq!(*response.status_code(), 400);
131        assert!(!response.is_success());
132        pretty_assert_eq!(response.request_id().as_str(), "req_789");
133        assert!(response.success_body().is_none());
134        assert!(response.error_body().is_some());
135    }
136
137    #[test]
138    fn test_missing_body() {
139        let json_data = json!({
140            "status_code": 500,
141            "request_id": "req_000",
142            "body": {}
143        });
144
145        let result: Result<BatchResponseContent, _> = serde_json::from_value(json_data);
146        assert!(result.is_err(), "Deserialization should fail if body is invalid");
147    }
148
149    #[test]
150    fn test_full_batch_deserialization() {
151        let json = r#"
152        {
153            "id": "batch_req_673d5e5fc66481908be3f82f25681838",
154            "custom_id": "request-0",
155            "response": {
156                "status_code": 200,
157                "request_id": "7b003085175d218b0ceb2b79d7f60bca",
158                "body": {
159                    "id": "chatcmpl-AVW7Z2Dd49g7Zq5eVExww6dlKA8T9",
160                    "object": "chat.completion",
161                    "created": 1732075005,
162                    "model": "gpt-4o-2024-08-06",
163                    "choices": [{
164                        "index": 0,
165                        "message": {
166                            "role": "assistant",
167                            "content": "Response content here.",
168                            "refusal": null
169                        },
170                        "logprobs": null,
171                        "finish_reason": "stop"
172                    }],
173                    "usage": {
174                        "prompt_tokens": 1528,
175                        "completion_tokens": 2891,
176                        "total_tokens": 4419
177                    },
178                    "system_fingerprint": "fp_7f6be3efb0"
179                }
180            },
181            "error": null
182        }
183        "#;
184
185        // Assuming you have defined BatchResponseRecord and related structs
186        let batch_response: BatchResponseRecord = serde_json::from_str(json).unwrap();
187        let response = batch_response.response();
188
189        // Accessing fields directly through BatchResponseBody methods
190        let body = response.body();
191
192        pretty_assert_eq!(body.id(), Some(&"chatcmpl-AVW7Z2Dd49g7Zq5eVExww6dlKA8T9".to_string()));
193        pretty_assert_eq!(body.object(), Some(&"chat.completion".to_string()));
194        pretty_assert_eq!(body.model(), Some(&"gpt-4o-2024-08-06".to_string()));
195        pretty_assert_eq!(body.system_fingerprint(), Some("fp_7f6be3efb0".to_string()));
196
197        // Access choices
198        if let Some(choices) = body.choices() {
199            pretty_assert_eq!(choices.len(), 1);
200            let choice = &choices[0];
201            pretty_assert_eq!(*choice.index(), 0);
202            pretty_assert_eq!(choice.finish_reason(), &FinishReason::Stop);
203            pretty_assert_eq!(choice.message().content(), "Response content here.");
204        } else {
205            panic!("Expected choices in the response body");
206        }
207    }
208}