1use reqwest::RequestBuilder;
2use super::OpenAiClient;
3use async_trait::async_trait;
4use crate::{ByUrlRequest, DeleteResponse, DownloadRequest, FormRequest, GetRequest};
5use std::io;
6use std::io::{Error, ErrorKind};
7use std::path::PathBuf;
8use reqwest::multipart::{Form, Part};
9use serde::{Serialize, Deserialize};
10use with_id::WithRefId;
11use crate::conversions::AsyncTryFrom;
12use crate::file_to_part;
13use derive_more::*;
14use crate::fine_tunes::FineTuneFileInfo;
15
16#[derive(Serialize, Deserialize, Debug, Clone)]
26pub struct FileListResponse {
27 pub data: Vec<FileInfo>,
28 pub object: String,
29}
30
31#[async_trait]
32impl GetRequest for FileListResponse {
33 const ENDPOINT: &'static str = "/files";
34}
35
36
37#[derive(Serialize, Deserialize, Debug, Clone, WithRefId)]
38pub struct FileInfo {
39 pub id: String,
40 pub object: String,
41 pub bytes: i64,
42 pub created_at: i64,
43 pub filename: String,
44 pub purpose: String,
45}
46
47impl From<FineTuneFileInfo> for FileInfo{
48 fn from(value: FineTuneFileInfo) -> Self {
49 FileInfo{
50 id: value.id,
51 object: value.object,
52 bytes: value.bytes,
53 created_at: value.created_at,
54 filename: value.filename,
55 purpose: value.purpose,
56 }
57 }
58}
59
60#[derive(Serialize, Deserialize, Debug, Clone, WithRefId, Constructor)]
71pub struct FileDeleteRequest{
72 #[id]
73 file_id:String
74}
75
76impl From<FileInfo> for FileDeleteRequest {
77 fn from(value: FileInfo) -> Self {
78 FileDeleteRequest{
79 file_id:value.id
80 }
81 }
82}
83
84impl ByUrlRequest<DeleteResponse> for FileDeleteRequest{
85 const ENDPOINT: &'static str = "/files/";
86 const SUFFIX: &'static str = "";
87
88 fn builder(client: &OpenAiClient, final_url: String) -> RequestBuilder {
89 client.client.delete(final_url)
90 }
91}
92
93#[derive(Serialize, Deserialize, Debug, Clone, WithRefId, Constructor)]
104pub struct FileInfoRequest{
105 #[id]
106 file_id:String
107}
108
109impl ByUrlRequest<FileInfo> for FileInfoRequest{
110 const ENDPOINT: &'static str = "/files/";
111 const SUFFIX: &'static str = "";
112}
113#[derive(Serialize, Deserialize, Debug, Clone, WithRefId, Constructor)]
124pub struct FileDownloadRequest{
125 #[id]
126 file_id:String
127}
128
129impl DownloadRequest for FileDownloadRequest{
130 const ENDPOINT: &'static str = "/files/";
131 const SUFFIX: &'static str = "/content";
132}
133
134impl From<FileInfo> for FileDownloadRequest {
135 fn from(value: FileInfo) -> Self {
136 FileDownloadRequest{
137 file_id:value.id
138 }
139 }
140}
141
142#[derive(Serialize, Deserialize, Debug, Clone)]
153pub struct FileUploadRequest{
154 file:PathBuf,
155 purpose:String
156}
157
158
159impl FormRequest<FileInfo> for FileUploadRequest{
160 const ENDPOINT: &'static str = "/files";
161}
162
163impl FileUploadRequest {
164
165 pub fn new(file:PathBuf, purpose:String) ->Result<FileUploadRequest,Error>{
167 if file.exists() {
168 Ok(
169 FileUploadRequest {
170 file,
171 purpose
172 }
173 )
174 }else {
175 Err(Error::new(ErrorKind::NotFound, "File does not exist"))
176 }
177 }
178 pub fn with_str(file:&str,purpose:&str)->Result<FileUploadRequest,Error>{
180 let path = PathBuf::from(file);
181 if path.exists() {
182 Ok(
183 FileUploadRequest {
184 file: path,
185 purpose: purpose.to_string()
186 }
187 )
188 }else {
189 Err(io::Error::new(ErrorKind::NotFound, "File does not exist"))
190 }
191 }
192}
193
194#[async_trait]
195impl AsyncTryFrom<FileUploadRequest> for Form{
196 type Error = io::Error;
197
198 async fn try_from(value: FileUploadRequest) -> anyhow::Result<Self, Self::Error> {
199 let form =
200 Form::new()
201 .part("purpose",Part::text(value.purpose))
202 .part("file",file_to_part(&value.file).await?);
203 Ok(form)
204 }
205}
206
207