1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
use crate::error::LingerError;
use crate::RequestId;
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
/// EN: Request body for `POST /v1/batches`.
/// 中文:`POST /v1/batches` 的请求体。
#[derive(Clone, Debug, Serialize, PartialEq)]
#[non_exhaustive]
pub struct CreateBatchRequest {
/// EN: Uploaded JSONL input file id.
/// 中文:已上传的 JSONL 输入文件 ID。
pub input_file_id: String,
/// EN: Endpoint each batch line targets.
/// 中文:batch 每一行所请求的端点。
pub endpoint: String,
/// EN: Batch completion window, currently such as `24h`.
/// 中文:batch 完成窗口,当前例如 `24h`。
pub completion_window: String,
/// EN: Optional metadata attached to the batch.
/// 中文:附加到 batch 的可选元数据。
#[serde(skip_serializing_if = "BTreeMap::is_empty")]
pub metadata: BTreeMap<String, String>,
/// EN: Forward-compatible optional fields not yet covered by handwritten types.
/// 中文:手写类型尚未覆盖的前向兼容可选字段。
#[serde(flatten)]
pub extra: BTreeMap<String, Value>,
}
impl CreateBatchRequest {
/// EN: Starts building a batch request.
/// 中文:开始构建 batch 请求。
pub fn builder() -> CreateBatchRequestBuilder {
CreateBatchRequestBuilder::default()
}
}
/// EN: Builder for create-batch requests.
/// 中文:创建 batch 请求的构建器。
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct CreateBatchRequestBuilder {
input_file_id: Option<String>,
endpoint: Option<String>,
completion_window: Option<String>,
metadata: BTreeMap<String, String>,
extra: BTreeMap<String, Value>,
}
impl CreateBatchRequestBuilder {
/// EN: Sets the uploaded input file id.
/// 中文:设置已上传的输入文件 ID。
pub fn input_file_id(mut self, input_file_id: impl Into<String>) -> Self {
self.input_file_id = Some(input_file_id.into());
self
}
/// EN: Sets the target endpoint.
/// 中文:设置目标端点。
pub fn endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.endpoint = Some(endpoint.into());
self
}
/// EN: Sets the completion window.
/// 中文:设置完成窗口。
pub fn completion_window(mut self, completion_window: impl Into<String>) -> Self {
self.completion_window = Some(completion_window.into());
self
}
/// EN: Adds a metadata entry.
/// 中文:添加一项元数据。
pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
/// EN: Adds a forward-compatible JSON field.
/// 中文:添加前向兼容的 JSON 字段。
pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
self.extra.insert(name.into(), value);
self
}
/// EN: Builds and validates the request.
/// 中文:构建并校验请求。
pub fn build(self) -> Result<CreateBatchRequest, LingerError> {
let input_file_id = self
.input_file_id
.filter(|value| !value.trim().is_empty())
.ok_or_else(|| LingerError::invalid_config("input_file_id is required"))?;
let endpoint = self
.endpoint
.filter(|value| !value.trim().is_empty())
.ok_or_else(|| LingerError::invalid_config("endpoint is required"))?;
let completion_window = self
.completion_window
.filter(|value| !value.trim().is_empty())
.ok_or_else(|| LingerError::invalid_config("completion_window is required"))?;
if self
.metadata
.iter()
.any(|(key, value)| key.trim().is_empty() || value.is_empty())
{
return Err(LingerError::invalid_config(
"metadata keys and values must not be empty",
));
}
Ok(CreateBatchRequest {
input_file_id,
endpoint,
completion_window,
metadata: self.metadata,
extra: self.extra,
})
}
}
/// EN: Batch object returned by the Batches API.
/// 中文:Batches API 返回的 batch 对象。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[non_exhaustive]
pub struct Batch {
/// EN: Batch id.
/// 中文:batch ID。
pub id: String,
/// EN: API object type.
/// 中文:API 对象类型。
pub object: String,
/// EN: Target endpoint for requests in this batch.
/// 中文:此 batch 中请求的目标端点。
pub endpoint: String,
/// EN: Batch validation or processing errors, when returned.
/// 中文:batch 校验或处理错误,如响应中存在。
#[serde(default)]
pub errors: Option<Value>,
/// EN: Uploaded input file id.
/// 中文:已上传的输入文件 ID。
pub input_file_id: String,
/// EN: Batch completion window.
/// 中文:batch 完成窗口。
pub completion_window: String,
/// EN: Current batch status.
/// 中文:当前 batch 状态。
pub status: String,
/// EN: Output file id, when available.
/// 中文:输出文件 ID,如可用。
#[serde(default)]
pub output_file_id: Option<String>,
/// EN: Error file id, when available.
/// 中文:错误文件 ID,如可用。
#[serde(default)]
pub error_file_id: Option<String>,
/// EN: Unix timestamp for creation.
/// 中文:创建时间的 Unix 时间戳。
pub created_at: u64,
/// EN: Unix timestamp for in-progress transition.
/// 中文:进入进行中状态的 Unix 时间戳。
#[serde(default)]
pub in_progress_at: Option<u64>,
/// EN: Unix timestamp for expiration.
/// 中文:过期时间的 Unix 时间戳。
#[serde(default)]
pub expires_at: Option<u64>,
/// EN: Unix timestamp for finalizing transition.
/// 中文:进入最终化状态的 Unix 时间戳。
#[serde(default)]
pub finalizing_at: Option<u64>,
/// EN: Unix timestamp for completion.
/// 中文:完成时间的 Unix 时间戳。
#[serde(default)]
pub completed_at: Option<u64>,
/// EN: Unix timestamp for failure.
/// 中文:失败时间的 Unix 时间戳。
#[serde(default)]
pub failed_at: Option<u64>,
/// EN: Unix timestamp for expiration completion.
/// 中文:过期完成时间的 Unix 时间戳。
#[serde(default)]
pub expired_at: Option<u64>,
/// EN: Unix timestamp for cancelling transition.
/// 中文:进入取消中状态的 Unix 时间戳。
#[serde(default)]
pub cancelling_at: Option<u64>,
/// EN: Unix timestamp for cancellation.
/// 中文:取消时间的 Unix 时间戳。
#[serde(default)]
pub cancelled_at: Option<u64>,
/// EN: Request counters for this batch.
/// 中文:此 batch 的请求计数。
pub request_counts: BatchRequestCounts,
/// EN: Metadata returned with this batch.
/// 中文:此 batch 返回的元数据。
#[serde(default, deserialize_with = "deserialize_null_default")]
pub metadata: BTreeMap<String, String>,
/// EN: Additional fields preserved for forward compatibility.
/// 中文:为前向兼容保留的额外字段。
#[serde(flatten)]
pub extra: BTreeMap<String, Value>,
/// EN: OpenAI request id from response headers.
/// 中文:响应头中的 OpenAI 请求 ID。
#[serde(skip)]
request_id: Option<RequestId>,
}
impl Batch {
pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
self.request_id = request_id;
self
}
/// EN: Returns the OpenAI request id, when present.
/// 中文:返回 OpenAI 请求 ID,如存在。
pub fn request_id(&self) -> Option<&RequestId> {
self.request_id.as_ref()
}
}
/// EN: Batch request counters.
/// 中文:batch 请求计数。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[non_exhaustive]
pub struct BatchRequestCounts {
/// EN: Total request count.
/// 中文:请求总数。
pub total: u64,
/// EN: Completed request count.
/// 中文:已完成请求数。
pub completed: u64,
/// EN: Failed request count.
/// 中文:失败请求数。
pub failed: u64,
}
/// EN: Paginated batch list returned by the Batches API.
/// 中文:Batches API 返回的分页 batch 列表。
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[non_exhaustive]
pub struct BatchListPage {
/// EN: API list object type.
/// 中文:API 列表对象类型。
pub object: String,
/// EN: Batches on this page.
/// 中文:本页 batch。
#[serde(default)]
pub data: Vec<Batch>,
/// EN: First batch id on this page.
/// 中文:本页第一个 batch ID。
#[serde(default)]
pub first_id: Option<String>,
/// EN: Last batch id on this page.
/// 中文:本页最后一个 batch ID。
#[serde(default)]
pub last_id: Option<String>,
/// EN: Whether more batches are available.
/// 中文:是否还有更多 batch。
pub has_more: bool,
/// EN: OpenAI request id from response headers.
/// 中文:响应头中的 OpenAI 请求 ID。
#[serde(skip)]
request_id: Option<RequestId>,
}
impl BatchListPage {
pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
self.request_id = request_id;
self
}
/// EN: Returns the OpenAI request id, when present.
/// 中文:返回 OpenAI 请求 ID,如存在。
pub fn request_id(&self) -> Option<&RequestId> {
self.request_id.as_ref()
}
}
fn deserialize_null_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de> + Default,
{
Ok(Option::<T>::deserialize(deserializer)?.unwrap_or_default())
}