Skip to main content

linger_openai_sdk/
vector_stores.rs

1use crate::error::LingerError;
2use crate::RequestId;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7/// EN: Request body for `POST /v1/vector_stores`.
8/// 中文:`POST /v1/vector_stores` 的请求体。
9#[derive(Clone, Debug, Serialize, PartialEq)]
10#[non_exhaustive]
11pub struct CreateVectorStoreRequest {
12    /// EN: Optional vector store name.
13    /// 中文:可选的向量存储名称。
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub name: Option<String>,
16    /// EN: Initial file ids to attach to the vector store.
17    /// 中文:要附加到向量存储的初始文件 ID。
18    #[serde(skip_serializing_if = "Vec::is_empty")]
19    pub file_ids: Vec<String>,
20    /// EN: Optional metadata.
21    /// 中文:可选元数据。
22    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
23    pub metadata: BTreeMap<String, String>,
24    /// EN: Forward-compatible optional fields not yet covered by handwritten types.
25    /// 中文:手写类型尚未覆盖的前向兼容可选字段。
26    #[serde(flatten)]
27    pub extra: BTreeMap<String, Value>,
28}
29
30impl CreateVectorStoreRequest {
31    /// EN: Starts building a vector store creation request.
32    /// 中文:开始构建向量存储创建请求。
33    pub fn builder() -> CreateVectorStoreRequestBuilder {
34        CreateVectorStoreRequestBuilder::default()
35    }
36}
37
38/// EN: Builder for vector store creation requests.
39/// 中文:向量存储创建请求的构建器。
40#[derive(Clone, Debug, Default)]
41#[non_exhaustive]
42pub struct CreateVectorStoreRequestBuilder {
43    name: Option<String>,
44    file_ids: Vec<String>,
45    metadata: BTreeMap<String, String>,
46    extra: BTreeMap<String, Value>,
47}
48
49impl CreateVectorStoreRequestBuilder {
50    /// EN: Sets the optional vector store name.
51    /// 中文:设置可选的向量存储名称。
52    pub fn name(mut self, name: impl Into<String>) -> Self {
53        self.name = Some(name.into());
54        self
55    }
56
57    /// EN: Adds an initial file id.
58    /// 中文:添加一个初始文件 ID。
59    pub fn file_id(mut self, file_id: impl Into<String>) -> Self {
60        self.file_ids.push(file_id.into());
61        self
62    }
63
64    /// EN: Replaces the initial file id list.
65    /// 中文:替换初始文件 ID 列表。
66    pub fn file_ids(mut self, file_ids: impl IntoIterator<Item = impl Into<String>>) -> Self {
67        self.file_ids = file_ids.into_iter().map(Into::into).collect();
68        self
69    }
70
71    /// EN: Adds a metadata key/value pair.
72    /// 中文:添加一个元数据键值对。
73    pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
74        self.metadata.insert(key.into(), value.into());
75        self
76    }
77
78    /// EN: Adds a forward-compatible JSON field.
79    /// 中文:添加前向兼容的 JSON 字段。
80    pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
81        self.extra.insert(name.into(), value);
82        self
83    }
84
85    /// EN: Builds and validates the request.
86    /// 中文:构建并校验请求。
87    pub fn build(self) -> Result<CreateVectorStoreRequest, LingerError> {
88        validate_optional_string("name", self.name.as_deref())?;
89        for file_id in &self.file_ids {
90            if file_id.trim().is_empty() {
91                return Err(LingerError::invalid_config(
92                    "file_ids must not contain empty values",
93                ));
94            }
95        }
96        for key in self.metadata.keys() {
97            if key.trim().is_empty() {
98                return Err(LingerError::invalid_config(
99                    "metadata keys must not be empty",
100                ));
101            }
102        }
103        Ok(CreateVectorStoreRequest {
104            name: self.name,
105            file_ids: self.file_ids,
106            metadata: self.metadata,
107            extra: self.extra,
108        })
109    }
110}
111
112/// EN: Request body for `POST /v1/vector_stores/{vector_store_id}`.
113/// 中文:`POST /v1/vector_stores/{vector_store_id}` 的请求体。
114#[derive(Clone, Debug, Default, Serialize, PartialEq)]
115#[non_exhaustive]
116pub struct ModifyVectorStoreRequest {
117    /// EN: Updated vector store name.
118    /// 中文:更新后的向量存储名称。
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub name: Option<String>,
121    /// EN: Updated metadata.
122    /// 中文:更新后的元数据。
123    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
124    pub metadata: BTreeMap<String, String>,
125    /// EN: Updated expiration policy.
126    /// 中文:更新后的过期策略。
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub expires_after: Option<Value>,
129}
130
131impl ModifyVectorStoreRequest {
132    /// EN: Starts building a vector store modification request.
133    /// 中文:开始构建向量存储修改请求。
134    pub fn builder() -> ModifyVectorStoreRequestBuilder {
135        ModifyVectorStoreRequestBuilder::default()
136    }
137}
138
139/// EN: Builder for vector store modification requests.
140/// 中文:向量存储修改请求的构建器。
141#[derive(Clone, Debug, Default)]
142#[non_exhaustive]
143pub struct ModifyVectorStoreRequestBuilder {
144    name: Option<String>,
145    metadata: BTreeMap<String, String>,
146    expires_after: Option<Value>,
147}
148
149impl ModifyVectorStoreRequestBuilder {
150    /// EN: Sets the updated vector store name.
151    /// 中文:设置更新后的向量存储名称。
152    pub fn name(mut self, name: impl Into<String>) -> Self {
153        self.name = Some(name.into());
154        self
155    }
156
157    /// EN: Adds an updated metadata key/value pair.
158    /// 中文:添加一个更新后的元数据键值对。
159    pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
160        self.metadata.insert(key.into(), value.into());
161        self
162    }
163
164    /// EN: Sets the updated expiration policy.
165    /// 中文:设置更新后的过期策略。
166    pub fn expires_after(mut self, expires_after: Value) -> Self {
167        self.expires_after = Some(expires_after);
168        self
169    }
170
171    /// EN: Builds and validates the request.
172    /// 中文:构建并校验请求。
173    pub fn build(self) -> Result<ModifyVectorStoreRequest, LingerError> {
174        validate_optional_string("name", self.name.as_deref())?;
175        validate_metadata(&self.metadata)?;
176        validate_optional_json_value("expires_after", self.expires_after.as_ref())?;
177        Ok(ModifyVectorStoreRequest {
178            name: self.name,
179            metadata: self.metadata,
180            expires_after: self.expires_after,
181        })
182    }
183}
184
185/// EN: Request body for `POST /v1/vector_stores/{vector_store_id}/files`.
186/// 中文:`POST /v1/vector_stores/{vector_store_id}/files` 的请求体。
187#[derive(Clone, Debug, Serialize, PartialEq)]
188#[non_exhaustive]
189pub struct CreateVectorStoreFileRequest {
190    /// EN: File id to attach to the vector store.
191    /// 中文:要附加到向量存储的文件 ID。
192    pub file_id: String,
193    /// EN: Forward-compatible optional fields not yet covered by handwritten types.
194    /// 中文:手写类型尚未覆盖的前向兼容可选字段。
195    #[serde(flatten)]
196    pub extra: BTreeMap<String, Value>,
197}
198
199impl CreateVectorStoreFileRequest {
200    /// EN: Starts building a vector store file request.
201    /// 中文:开始构建向量存储文件请求。
202    pub fn builder() -> CreateVectorStoreFileRequestBuilder {
203        CreateVectorStoreFileRequestBuilder::default()
204    }
205}
206
207/// EN: Builder for vector store file requests.
208/// 中文:向量存储文件请求的构建器。
209#[derive(Clone, Debug, Default)]
210#[non_exhaustive]
211pub struct CreateVectorStoreFileRequestBuilder {
212    file_id: Option<String>,
213    extra: BTreeMap<String, Value>,
214}
215
216impl CreateVectorStoreFileRequestBuilder {
217    /// EN: Sets the file id to attach.
218    /// 中文:设置要附加的文件 ID。
219    pub fn file_id(mut self, file_id: impl Into<String>) -> Self {
220        self.file_id = Some(file_id.into());
221        self
222    }
223
224    /// EN: Adds a forward-compatible JSON field.
225    /// 中文:添加前向兼容的 JSON 字段。
226    pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
227        self.extra.insert(name.into(), value);
228        self
229    }
230
231    /// EN: Builds and validates the request.
232    /// 中文:构建并校验请求。
233    pub fn build(self) -> Result<CreateVectorStoreFileRequest, LingerError> {
234        Ok(CreateVectorStoreFileRequest {
235            file_id: required_string("file_id", self.file_id)?,
236            extra: self.extra,
237        })
238    }
239}
240
241/// EN: Request body for `POST /v1/vector_stores/{vector_store_id}/files/{file_id}`.
242/// 中文:`POST /v1/vector_stores/{vector_store_id}/files/{file_id}` 的请求体。
243#[derive(Clone, Debug, Default, Serialize, PartialEq)]
244#[non_exhaustive]
245pub struct ModifyVectorStoreFileRequest {
246    /// EN: Updated file attributes.
247    /// 中文:更新后的文件属性。
248    pub attributes: BTreeMap<String, Value>,
249}
250
251impl ModifyVectorStoreFileRequest {
252    /// EN: Starts building a vector store file modification request.
253    /// 中文:开始构建向量存储文件修改请求。
254    pub fn builder() -> ModifyVectorStoreFileRequestBuilder {
255        ModifyVectorStoreFileRequestBuilder::default()
256    }
257}
258
259/// EN: Builder for vector store file modification requests.
260/// 中文:向量存储文件修改请求的构建器。
261#[derive(Clone, Debug, Default)]
262#[non_exhaustive]
263pub struct ModifyVectorStoreFileRequestBuilder {
264    attributes: BTreeMap<String, Value>,
265}
266
267impl ModifyVectorStoreFileRequestBuilder {
268    /// EN: Adds an updated file attribute.
269    /// 中文:添加一个更新后的文件属性。
270    pub fn attribute(mut self, key: impl Into<String>, value: Value) -> Self {
271        self.attributes.insert(key.into(), value);
272        self
273    }
274
275    /// EN: Replaces all updated file attributes.
276    /// 中文:替换全部更新后的文件属性。
277    pub fn attributes(mut self, attributes: BTreeMap<String, Value>) -> Self {
278        self.attributes = attributes;
279        self
280    }
281
282    /// EN: Builds and validates the request.
283    /// 中文:构建并校验请求。
284    pub fn build(self) -> Result<ModifyVectorStoreFileRequest, LingerError> {
285        validate_attributes(&self.attributes, true)?;
286        Ok(ModifyVectorStoreFileRequest {
287            attributes: self.attributes,
288        })
289    }
290}
291
292/// EN: Request body for `POST /v1/vector_stores/{vector_store_id}/file_batches`.
293/// 中文:`POST /v1/vector_stores/{vector_store_id}/file_batches` 的请求体。
294#[derive(Clone, Debug, Serialize, PartialEq)]
295#[non_exhaustive]
296pub struct CreateVectorStoreFileBatchRequest {
297    /// EN: File ids to add to the vector store.
298    /// 中文:要添加到向量存储的文件 ID。
299    pub file_ids: Vec<String>,
300    /// EN: Forward-compatible optional fields not yet covered by handwritten types.
301    /// 中文:手写类型尚未覆盖的前向兼容可选字段。
302    #[serde(flatten)]
303    pub extra: BTreeMap<String, Value>,
304}
305
306impl CreateVectorStoreFileBatchRequest {
307    /// EN: Starts building a vector store file batch request.
308    /// 中文:开始构建向量存储文件批量请求。
309    pub fn builder() -> CreateVectorStoreFileBatchRequestBuilder {
310        CreateVectorStoreFileBatchRequestBuilder::default()
311    }
312}
313
314/// EN: Builder for vector store file batch requests.
315/// 中文:向量存储文件批量请求的构建器。
316#[derive(Clone, Debug, Default)]
317#[non_exhaustive]
318pub struct CreateVectorStoreFileBatchRequestBuilder {
319    file_ids: Vec<String>,
320    extra: BTreeMap<String, Value>,
321}
322
323impl CreateVectorStoreFileBatchRequestBuilder {
324    /// EN: Adds a file id to the batch.
325    /// 中文:向批量请求添加文件 ID。
326    pub fn file_id(mut self, file_id: impl Into<String>) -> Self {
327        self.file_ids.push(file_id.into());
328        self
329    }
330
331    /// EN: Replaces the file id list.
332    /// 中文:替换文件 ID 列表。
333    pub fn file_ids(mut self, file_ids: impl IntoIterator<Item = impl Into<String>>) -> Self {
334        self.file_ids = file_ids.into_iter().map(Into::into).collect();
335        self
336    }
337
338    /// EN: Adds a forward-compatible JSON field.
339    /// 中文:添加前向兼容的 JSON 字段。
340    pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
341        self.extra.insert(name.into(), value);
342        self
343    }
344
345    /// EN: Builds and validates the request.
346    /// 中文:构建并校验请求。
347    pub fn build(self) -> Result<CreateVectorStoreFileBatchRequest, LingerError> {
348        validate_non_empty_values("file_ids", &self.file_ids)?;
349        Ok(CreateVectorStoreFileBatchRequest {
350            file_ids: self.file_ids,
351            extra: self.extra,
352        })
353    }
354}
355
356/// EN: Request body for `POST /v1/vector_stores/{vector_store_id}/search`.
357/// 中文:`POST /v1/vector_stores/{vector_store_id}/search` 的请求体。
358#[derive(Clone, Debug, Serialize, PartialEq)]
359#[non_exhaustive]
360pub struct CreateVectorStoreSearchRequest {
361    /// EN: Search query text.
362    /// 中文:搜索查询文本。
363    pub query: String,
364    /// EN: Optional maximum number of search results.
365    /// 中文:可选的最大搜索结果数量。
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub max_num_results: Option<u32>,
368    /// EN: Optional metadata filter expression.
369    /// 中文:可选的元数据过滤表达式。
370    #[serde(rename = "filters", skip_serializing_if = "Option::is_none")]
371    pub filter: Option<Value>,
372    /// EN: Forward-compatible optional fields not yet covered by handwritten types.
373    /// 中文:手写类型尚未覆盖的前向兼容可选字段。
374    #[serde(flatten)]
375    pub extra: BTreeMap<String, Value>,
376}
377
378impl CreateVectorStoreSearchRequest {
379    /// EN: Starts building a vector store search request.
380    /// 中文:开始构建向量存储搜索请求。
381    pub fn builder() -> CreateVectorStoreSearchRequestBuilder {
382        CreateVectorStoreSearchRequestBuilder::default()
383    }
384}
385
386/// EN: Builder for vector store search requests.
387/// 中文:向量存储搜索请求的构建器。
388#[derive(Clone, Debug, Default)]
389#[non_exhaustive]
390pub struct CreateVectorStoreSearchRequestBuilder {
391    query: Option<String>,
392    max_num_results: Option<u32>,
393    filter: Option<Value>,
394    extra: BTreeMap<String, Value>,
395}
396
397impl CreateVectorStoreSearchRequestBuilder {
398    /// EN: Sets the search query.
399    /// 中文:设置搜索查询。
400    pub fn query(mut self, query: impl Into<String>) -> Self {
401        self.query = Some(query.into());
402        self
403    }
404
405    /// EN: Sets the maximum number of search results.
406    /// 中文:设置最大搜索结果数量。
407    pub fn max_num_results(mut self, max_num_results: u32) -> Self {
408        self.max_num_results = Some(max_num_results);
409        self
410    }
411
412    /// EN: Sets a metadata filter expression.
413    /// 中文:设置元数据过滤表达式。
414    pub fn filter(mut self, filter: Value) -> Self {
415        self.filter = Some(filter);
416        self
417    }
418
419    /// EN: Adds a forward-compatible JSON field.
420    /// 中文:添加前向兼容的 JSON 字段。
421    pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
422        self.extra.insert(name.into(), value);
423        self
424    }
425
426    /// EN: Builds and validates the request.
427    /// 中文:构建并校验请求。
428    pub fn build(self) -> Result<CreateVectorStoreSearchRequest, LingerError> {
429        let query = required_string("query", self.query)?;
430        if self
431            .max_num_results
432            .is_some_and(|value| !(1..=50).contains(&value))
433        {
434            return Err(LingerError::invalid_config(
435                "max_num_results must be between 1 and 50",
436            ));
437        }
438        if self.filter.as_ref().is_some_and(Value::is_null) {
439            return Err(LingerError::invalid_config("filters must not be null"));
440        }
441        validate_extra_fields(&self.extra)?;
442        Ok(CreateVectorStoreSearchRequest {
443            query,
444            max_num_results: self.max_num_results,
445            filter: self.filter,
446            extra: self.extra,
447        })
448    }
449}
450
451/// EN: Vector store object returned by the Vector Stores API.
452/// 中文:Vector Stores API 返回的向量存储对象。
453#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
454#[non_exhaustive]
455pub struct VectorStore {
456    /// EN: Vector store id.
457    /// 中文:向量存储 ID。
458    pub id: String,
459    /// EN: API object type.
460    /// 中文:API 对象类型。
461    pub object: String,
462    /// EN: Unix timestamp for creation.
463    /// 中文:创建时间的 Unix 时间戳。
464    pub created_at: u64,
465    /// EN: Vector store name, when returned.
466    /// 中文:向量存储名称,如响应中存在。
467    #[serde(default)]
468    pub name: Option<String>,
469    /// EN: Bytes used by the vector store.
470    /// 中文:向量存储使用的字节数。
471    #[serde(default, alias = "usage_bytes")]
472    pub bytes: u64,
473    /// EN: File count summary.
474    /// 中文:文件数量汇总。
475    pub file_counts: VectorStoreFileCounts,
476    /// EN: Vector store status.
477    /// 中文:向量存储状态。
478    pub status: String,
479    /// EN: Expiration policy, when returned.
480    /// 中文:过期策略,如响应中存在。
481    #[serde(default)]
482    pub expires_after: Option<Value>,
483    /// EN: Unix timestamp for expiration, when returned.
484    /// 中文:过期时间的 Unix 时间戳,如响应中存在。
485    #[serde(default)]
486    pub expires_at: Option<u64>,
487    /// EN: Last active timestamp, when returned.
488    /// 中文:最后活跃时间戳,如响应中存在。
489    #[serde(default)]
490    pub last_active_at: Option<u64>,
491    /// EN: Metadata returned by the API.
492    /// 中文:API 返回的元数据。
493    #[serde(default)]
494    pub metadata: BTreeMap<String, String>,
495    /// EN: Additional fields preserved for forward compatibility.
496    /// 中文:为前向兼容保留的额外字段。
497    #[serde(flatten)]
498    pub extra: BTreeMap<String, Value>,
499    /// EN: OpenAI request id from response headers.
500    /// 中文:响应头中的 OpenAI 请求 ID。
501    #[serde(skip)]
502    request_id: Option<RequestId>,
503}
504
505impl VectorStore {
506    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
507        self.request_id = request_id;
508        self
509    }
510
511    /// EN: Returns the OpenAI request id, when present.
512    /// 中文:返回 OpenAI 请求 ID,如存在。
513    pub fn request_id(&self) -> Option<&RequestId> {
514        self.request_id.as_ref()
515    }
516}
517
518/// EN: File count summary for a vector store.
519/// 中文:向量存储的文件数量汇总。
520#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
521#[non_exhaustive]
522pub struct VectorStoreFileCounts {
523    /// EN: Number of files still processing.
524    /// 中文:仍在处理的文件数量。
525    pub in_progress: u64,
526    /// EN: Number of completed files.
527    /// 中文:已完成文件数量。
528    pub completed: u64,
529    /// EN: Number of failed files.
530    /// 中文:失败文件数量。
531    pub failed: u64,
532    /// EN: Number of cancelled files.
533    /// 中文:已取消文件数量。
534    pub cancelled: u64,
535    /// EN: Total file count.
536    /// 中文:文件总数。
537    pub total: u64,
538}
539
540/// EN: Vector store file object returned by the Vector Store Files API.
541/// 中文:Vector Store Files API 返回的向量存储文件对象。
542#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
543#[non_exhaustive]
544pub struct VectorStoreFile {
545    /// EN: File id.
546    /// 中文:文件 ID。
547    pub id: String,
548    /// EN: API object type.
549    /// 中文:API 对象类型。
550    pub object: String,
551    /// EN: Unix timestamp for creation.
552    /// 中文:创建时间的 Unix 时间戳。
553    pub created_at: u64,
554    /// EN: Parent vector store id.
555    /// 中文:父向量存储 ID。
556    pub vector_store_id: String,
557    /// EN: File status in the vector store.
558    /// 中文:文件在向量存储中的状态。
559    pub status: String,
560    /// EN: Last file processing error, when returned.
561    /// 中文:最后一次文件处理错误,如响应中存在。
562    #[serde(default)]
563    pub last_error: Option<Value>,
564    /// EN: Bytes used by this vector store file.
565    /// 中文:此向量存储文件使用的字节数。
566    #[serde(default)]
567    pub usage_bytes: u64,
568    /// EN: Chunking strategy returned by the API, when present.
569    /// 中文:API 返回的分块策略,如存在。
570    #[serde(default)]
571    pub chunking_strategy: Option<Value>,
572    /// EN: File attributes returned by the API.
573    /// 中文:API 返回的文件属性。
574    #[serde(default)]
575    pub attributes: BTreeMap<String, Value>,
576    /// EN: Additional fields preserved for forward compatibility.
577    /// 中文:为前向兼容保留的额外字段。
578    #[serde(flatten)]
579    pub extra: BTreeMap<String, Value>,
580    /// EN: OpenAI request id from response headers.
581    /// 中文:响应头中的 OpenAI 请求 ID。
582    #[serde(skip)]
583    request_id: Option<RequestId>,
584}
585
586impl VectorStoreFile {
587    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
588        self.request_id = request_id;
589        self
590    }
591
592    /// EN: Returns the OpenAI request id, when present.
593    /// 中文:返回 OpenAI 请求 ID,如存在。
594    pub fn request_id(&self) -> Option<&RequestId> {
595        self.request_id.as_ref()
596    }
597}
598
599/// EN: Paginated vector store file list.
600/// 中文:分页向量存储文件列表。
601#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
602#[non_exhaustive]
603pub struct VectorStoreFilePage {
604    /// EN: API list object type.
605    /// 中文:API 列表对象类型。
606    pub object: String,
607    /// EN: Files on this page.
608    /// 中文:本页文件。
609    #[serde(default)]
610    pub data: Vec<VectorStoreFile>,
611    /// EN: First file id on this page.
612    /// 中文:本页第一个文件 ID。
613    #[serde(default)]
614    pub first_id: Option<String>,
615    /// EN: Last file id on this page.
616    /// 中文:本页最后一个文件 ID。
617    #[serde(default)]
618    pub last_id: Option<String>,
619    /// EN: Whether more files are available.
620    /// 中文:是否还有更多文件。
621    pub has_more: bool,
622    /// EN: OpenAI request id from response headers.
623    /// 中文:响应头中的 OpenAI 请求 ID。
624    #[serde(skip)]
625    request_id: Option<RequestId>,
626}
627
628impl VectorStoreFilePage {
629    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
630        self.request_id = request_id;
631        self
632    }
633
634    /// EN: Returns the OpenAI request id, when present.
635    /// 中文:返回 OpenAI 请求 ID,如存在。
636    pub fn request_id(&self) -> Option<&RequestId> {
637        self.request_id.as_ref()
638    }
639}
640
641/// EN: Parsed content block returned for a vector store file.
642/// 中文:向量存储文件返回的已解析内容块。
643#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
644#[non_exhaustive]
645pub struct VectorStoreFileContent {
646    /// EN: Content type, currently usually `text`.
647    /// 中文:内容类型,目前通常为 `text`。
648    #[serde(default)]
649    pub r#type: Option<String>,
650    /// EN: Text content, when returned.
651    /// 中文:文本内容,如响应中存在。
652    #[serde(default)]
653    pub text: Option<String>,
654    /// EN: Additional fields preserved for forward compatibility.
655    /// 中文:为前向兼容保留的额外字段。
656    #[serde(flatten)]
657    pub extra: BTreeMap<String, Value>,
658}
659
660/// EN: Page of parsed vector store file content blocks.
661/// 中文:向量存储文件已解析内容块的分页结果。
662#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
663#[non_exhaustive]
664pub struct VectorStoreFileContentPage {
665    /// EN: API list object type.
666    /// 中文:API 列表对象类型。
667    pub object: String,
668    /// EN: Parsed content blocks on this page.
669    /// 中文:本页中的已解析内容块。
670    #[serde(default)]
671    pub data: Vec<VectorStoreFileContent>,
672    /// EN: Whether more content blocks are available.
673    /// 中文:是否还有更多内容块。
674    #[serde(default)]
675    pub has_more: bool,
676    /// EN: Additional fields preserved for forward compatibility.
677    /// 中文:为前向兼容保留的额外字段。
678    #[serde(flatten)]
679    pub extra: BTreeMap<String, Value>,
680    /// EN: OpenAI request id from response headers.
681    /// 中文:响应头中的 OpenAI 请求 ID。
682    #[serde(skip)]
683    request_id: Option<RequestId>,
684}
685
686impl VectorStoreFileContentPage {
687    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
688        self.request_id = request_id;
689        self
690    }
691
692    /// EN: Returns the OpenAI request id, when present.
693    /// 中文:返回 OpenAI 请求 ID,如存在。
694    pub fn request_id(&self) -> Option<&RequestId> {
695        self.request_id.as_ref()
696    }
697}
698
699/// EN: Single vector store search result.
700/// 中文:单个向量存储搜索结果。
701#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
702#[non_exhaustive]
703pub struct VectorStoreSearchResult {
704    /// EN: File id that produced the result.
705    /// 中文:产生该结果的文件 ID。
706    pub file_id: String,
707    /// EN: File name, when returned.
708    /// 中文:文件名,如响应中存在。
709    #[serde(default)]
710    pub filename: Option<String>,
711    /// EN: Search relevance score, when returned.
712    /// 中文:搜索相关性分数,如响应中存在。
713    #[serde(default)]
714    pub score: Option<f64>,
715    /// EN: Result content blocks returned by the API.
716    /// 中文:API 返回的结果内容块。
717    #[serde(default)]
718    pub content: Vec<Value>,
719    /// EN: File attributes returned with the result.
720    /// 中文:结果附带的文件属性。
721    #[serde(default)]
722    pub attributes: BTreeMap<String, Value>,
723    /// EN: Additional fields preserved for forward compatibility.
724    /// 中文:为前向兼容保留的额外字段。
725    #[serde(flatten)]
726    pub extra: BTreeMap<String, Value>,
727}
728
729/// EN: Paginated vector store search results.
730/// 中文:分页向量存储搜索结果。
731#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
732#[non_exhaustive]
733pub struct VectorStoreSearchPage {
734    /// EN: API page object type.
735    /// 中文:API 分页对象类型。
736    pub object: String,
737    /// EN: Search results on this page.
738    /// 中文:本页搜索结果。
739    #[serde(default)]
740    pub data: Vec<VectorStoreSearchResult>,
741    /// EN: Whether more search results are available.
742    /// 中文:是否还有更多搜索结果。
743    pub has_more: bool,
744    /// EN: Cursor for the next page, when returned.
745    /// 中文:下一页游标,如响应中存在。
746    #[serde(default)]
747    pub next_page: Option<String>,
748    /// EN: Additional fields preserved for forward compatibility.
749    /// 中文:为前向兼容保留的额外字段。
750    #[serde(flatten)]
751    pub extra: BTreeMap<String, Value>,
752    /// EN: OpenAI request id from response headers.
753    /// 中文:响应头中的 OpenAI 请求 ID。
754    #[serde(skip)]
755    request_id: Option<RequestId>,
756}
757
758impl VectorStoreSearchPage {
759    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
760        self.request_id = request_id;
761        self
762    }
763
764    /// EN: Returns the OpenAI request id, when present.
765    /// 中文:返回 OpenAI 请求 ID,如存在。
766    pub fn request_id(&self) -> Option<&RequestId> {
767        self.request_id.as_ref()
768    }
769}
770
771/// EN: Deletion result returned by the Vector Store Files API.
772/// 中文:Vector Store Files API 返回的删除结果。
773#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
774#[non_exhaustive]
775pub struct VectorStoreFileDeletion {
776    /// EN: Deleted file id.
777    /// 中文:已删除的文件 ID。
778    pub id: String,
779    /// EN: API object type.
780    /// 中文:API 对象类型。
781    pub object: String,
782    /// EN: Whether the vector store file was deleted.
783    /// 中文:向量存储文件是否已删除。
784    pub deleted: bool,
785    /// EN: OpenAI request id from response headers.
786    /// 中文:响应头中的 OpenAI 请求 ID。
787    #[serde(skip)]
788    request_id: Option<RequestId>,
789}
790
791impl VectorStoreFileDeletion {
792    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
793        self.request_id = request_id;
794        self
795    }
796
797    /// EN: Returns the OpenAI request id, when present.
798    /// 中文:返回 OpenAI 请求 ID,如存在。
799    pub fn request_id(&self) -> Option<&RequestId> {
800        self.request_id.as_ref()
801    }
802}
803
804/// EN: Vector store file batch object returned by the File Batches API.
805/// 中文:File Batches API 返回的向量存储文件批量对象。
806#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
807#[non_exhaustive]
808pub struct VectorStoreFileBatch {
809    /// EN: File batch id.
810    /// 中文:文件批量 ID。
811    pub id: String,
812    /// EN: API object type.
813    /// 中文:API 对象类型。
814    pub object: String,
815    /// EN: Unix timestamp for creation.
816    /// 中文:创建时间的 Unix 时间戳。
817    pub created_at: u64,
818    /// EN: Parent vector store id.
819    /// 中文:父向量存储 ID。
820    pub vector_store_id: String,
821    /// EN: File batch status.
822    /// 中文:文件批量状态。
823    pub status: String,
824    /// EN: File count summary.
825    /// 中文:文件数量汇总。
826    pub file_counts: VectorStoreFileCounts,
827    /// EN: Additional fields preserved for forward compatibility.
828    /// 中文:为前向兼容保留的额外字段。
829    #[serde(flatten)]
830    pub extra: BTreeMap<String, Value>,
831    /// EN: OpenAI request id from response headers.
832    /// 中文:响应头中的 OpenAI 请求 ID。
833    #[serde(skip)]
834    request_id: Option<RequestId>,
835}
836
837impl VectorStoreFileBatch {
838    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
839        self.request_id = request_id;
840        self
841    }
842
843    /// EN: Returns the OpenAI request id, when present.
844    /// 中文:返回 OpenAI 请求 ID,如存在。
845    pub fn request_id(&self) -> Option<&RequestId> {
846        self.request_id.as_ref()
847    }
848}
849
850/// EN: Paginated vector store list returned by the Vector Stores API.
851/// 中文:Vector Stores API 返回的分页向量存储列表。
852#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
853#[non_exhaustive]
854pub struct VectorStorePage {
855    /// EN: API list object type.
856    /// 中文:API 列表对象类型。
857    pub object: String,
858    /// EN: Vector stores on this page.
859    /// 中文:本页向量存储。
860    #[serde(default)]
861    pub data: Vec<VectorStore>,
862    /// EN: First vector store id on this page.
863    /// 中文:本页第一个向量存储 ID。
864    #[serde(default)]
865    pub first_id: Option<String>,
866    /// EN: Last vector store id on this page.
867    /// 中文:本页最后一个向量存储 ID。
868    #[serde(default)]
869    pub last_id: Option<String>,
870    /// EN: Whether more vector stores are available.
871    /// 中文:是否还有更多向量存储。
872    pub has_more: bool,
873    /// EN: OpenAI request id from response headers.
874    /// 中文:响应头中的 OpenAI 请求 ID。
875    #[serde(skip)]
876    request_id: Option<RequestId>,
877}
878
879impl VectorStorePage {
880    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
881        self.request_id = request_id;
882        self
883    }
884
885    /// EN: Returns the OpenAI request id, when present.
886    /// 中文:返回 OpenAI 请求 ID,如存在。
887    pub fn request_id(&self) -> Option<&RequestId> {
888        self.request_id.as_ref()
889    }
890}
891
892/// EN: Deletion result returned by the Vector Stores API.
893/// 中文:Vector Stores API 返回的删除结果。
894#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
895#[non_exhaustive]
896pub struct VectorStoreDeletion {
897    /// EN: Deleted vector store id.
898    /// 中文:已删除的向量存储 ID。
899    pub id: String,
900    /// EN: API object type.
901    /// 中文:API 对象类型。
902    pub object: String,
903    /// EN: Whether the vector store was deleted.
904    /// 中文:向量存储是否已删除。
905    pub deleted: bool,
906    /// EN: OpenAI request id from response headers.
907    /// 中文:响应头中的 OpenAI 请求 ID。
908    #[serde(skip)]
909    request_id: Option<RequestId>,
910}
911
912impl VectorStoreDeletion {
913    pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
914        self.request_id = request_id;
915        self
916    }
917
918    /// EN: Returns the OpenAI request id, when present.
919    /// 中文:返回 OpenAI 请求 ID,如存在。
920    pub fn request_id(&self) -> Option<&RequestId> {
921        self.request_id.as_ref()
922    }
923}
924
925fn validate_optional_string(name: &str, value: Option<&str>) -> Result<(), LingerError> {
926    if value.is_some_and(|value| value.trim().is_empty()) {
927        return Err(LingerError::invalid_config(format!(
928            "{name} must not be empty"
929        )));
930    }
931    Ok(())
932}
933
934fn validate_metadata(metadata: &BTreeMap<String, String>) -> Result<(), LingerError> {
935    for key in metadata.keys() {
936        if key.trim().is_empty() {
937            return Err(LingerError::invalid_config(
938                "metadata keys must not be empty",
939            ));
940        }
941    }
942    Ok(())
943}
944
945fn validate_optional_json_value(name: &str, value: Option<&Value>) -> Result<(), LingerError> {
946    if value.is_some_and(Value::is_null) {
947        return Err(LingerError::invalid_config(format!(
948            "{name} must not be null"
949        )));
950    }
951    Ok(())
952}
953
954fn validate_attributes(
955    attributes: &BTreeMap<String, Value>,
956    require_non_empty: bool,
957) -> Result<(), LingerError> {
958    if require_non_empty && attributes.is_empty() {
959        return Err(LingerError::invalid_config("attributes are required"));
960    }
961    for (key, value) in attributes {
962        if key.trim().is_empty() {
963            return Err(LingerError::invalid_config(
964                "attribute names must not be empty",
965            ));
966        }
967        if !(value.is_string() || value.is_number() || value.is_boolean()) {
968            return Err(LingerError::invalid_config(format!(
969                "attribute {key} must be a string, number, or boolean"
970            )));
971        }
972    }
973    Ok(())
974}
975
976fn required_string(name: &str, value: Option<String>) -> Result<String, LingerError> {
977    value
978        .filter(|value| !value.trim().is_empty())
979        .ok_or_else(|| LingerError::invalid_config(format!("{name} is required")))
980}
981
982fn validate_non_empty_values(name: &str, values: &[String]) -> Result<(), LingerError> {
983    if values.is_empty() {
984        return Err(LingerError::invalid_config(format!("{name} is required")));
985    }
986    if values.iter().any(|value| value.trim().is_empty()) {
987        return Err(LingerError::invalid_config(format!(
988            "{name} must not contain empty values"
989        )));
990    }
991    Ok(())
992}
993
994fn validate_extra_fields(extra: &BTreeMap<String, Value>) -> Result<(), LingerError> {
995    for (key, value) in extra {
996        if key.trim().is_empty() {
997            return Err(LingerError::invalid_config(
998                "extra field names must not be empty",
999            ));
1000        }
1001        if value.is_null() {
1002            return Err(LingerError::invalid_config(format!(
1003                "extra field {key} must not be null"
1004            )));
1005        }
1006    }
1007    Ok(())
1008}