Add assistant api

This commit is contained in:
Dongri Jin
2023-11-11 18:24:51 +09:00
parent 6e07047c27
commit cfca665c21
19 changed files with 966 additions and 48 deletions

64
examples/assistant.rs Normal file
View File

@ -0,0 +1,64 @@
use openai_api_rs::v1::api::Client;
use openai_api_rs::v1::assistant::AssistantRequest;
use openai_api_rs::v1::common::GPT4_1106_PREVIEW;
use openai_api_rs::v1::message::{CreateMessageRequest, MessageRole};
use openai_api_rs::v1::run::CreateRunRequest;
use openai_api_rs::v1::thread::CreateThreadRequest;
use std::collections::HashMap;
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string());
let mut tools = HashMap::new();
tools.insert("type".to_string(), "code_interpreter".to_string());
let req = AssistantRequest::new(GPT4_1106_PREVIEW.to_string());
req.clone()
.description("this is a test assistant".to_string());
req.clone().instructions("You are a personal math tutor. When asked a question, write and run Python code to answer the question.".to_string());
req.clone().tools(vec![tools]);
let result = client.create_assistant(req)?;
println!("{:?}", result.id);
let thread_req = CreateThreadRequest::new();
let thread_result = client.create_thread(thread_req)?;
println!("{:?}", thread_result.id.clone());
let message_req = CreateMessageRequest::new(
MessageRole::user,
"`I need to solve the equation 3x + 11 = 14. Can you help me?".to_string(),
);
let message_result = client.create_message(thread_result.id.clone(), message_req)?;
println!("{:?}", message_result.id.clone());
let run_req = CreateRunRequest::new(result.id);
let run_result = client.create_run(thread_result.id.clone(), run_req)?;
loop {
let run_result = client
.retrieve_run(thread_result.id.clone(), run_result.id.clone())
.unwrap();
if run_result.status == "completed" {
break;
} else {
println!("waiting...");
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
let list_message_result = client.list_messages(thread_result.id.clone()).unwrap();
for data in list_message_result.data {
for content in data.content {
println!(
"{:?}: {:?} {:?}",
data.role, content.text.value, content.text.annotations
);
}
}
Ok(())
}
// OPENAI_API_KEY=xxxx cargo run --package openai-api-rs --example assistant

View File

@ -1,12 +1,13 @@
use openai_api_rs::v1::api::Client;
use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest};
use openai_api_rs::v1::common::GPT4;
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(env::var("OPENAI_API_KEY").unwrap().to_string());
let req = ChatCompletionRequest::new(
chat_completion::GPT4.to_string(),
GPT4.to_string(),
vec![chat_completion::ChatCompletionMessage {
role: chat_completion::MessageRole::user,
content: String::from("What is Bitcoin?"),

View File

@ -1,5 +1,6 @@
use openai_api_rs::v1::api::Client;
use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest, FunctionCallType};
use openai_api_rs::v1::common::GPT3_5_TURBO_0613;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::{env, vec};
@ -30,7 +31,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
let req = ChatCompletionRequest::new(
chat_completion::GPT3_5_TURBO_0613.to_string(),
GPT3_5_TURBO_0613.to_string(),
vec![chat_completion::ChatCompletionMessage {
role: chat_completion::MessageRole::user,
content: String::from("What is the price of Ethereum?"),

View File

@ -1,5 +1,6 @@
use openai_api_rs::v1::api::Client;
use openai_api_rs::v1::chat_completion::{self, ChatCompletionRequest};
use openai_api_rs::v1::common::GPT3_5_TURBO_0613;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::{env, vec};
@ -30,7 +31,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
let req = ChatCompletionRequest::new(
chat_completion::GPT3_5_TURBO_0613.to_string(),
GPT3_5_TURBO_0613.to_string(),
vec![chat_completion::ChatCompletionMessage {
role: chat_completion::MessageRole::user,
content: String::from("What is the price of Ethereum?"),
@ -70,7 +71,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let coin = c.coin;
let req = ChatCompletionRequest::new(
chat_completion::GPT3_5_TURBO_0613.to_string(),
GPT3_5_TURBO_0613.to_string(),
vec![
chat_completion::ChatCompletionMessage {
role: chat_completion::MessageRole::user,

View File

@ -1,3 +1,7 @@
use crate::v1::assistant::{
AssistantFileObject, AssistantFileRequest, AssistantObject, AssistantRequest, DeletionStatus,
ListAssistant, ListAssistantFile,
};
use crate::v1::audio::{
AudioTranscriptionRequest, AudioTranscriptionResponse, AudioTranslationRequest,
AudioTranslationResponse,
@ -22,7 +26,16 @@ use crate::v1::image::{
ImageEditRequest, ImageEditResponse, ImageGenerationRequest, ImageGenerationResponse,
ImageVariationRequest, ImageVariationResponse,
};
use crate::v1::message::{
CreateMessageRequest, ListMessage, ListMessageFile, MessageFileObject, MessageObject,
ModifyMessageRequest,
};
use crate::v1::moderation::{CreateModerationRequest, CreateModerationResponse};
use crate::v1::run::{
CreateRunRequest, CreateThreadAndRunRequest, ListRun, ListRunStep, ModifyRunRequest, RunObject,
RunStepObject,
};
use crate::v1::thread::{CreateThreadRequest, ModifyThreadRequest, ThreadObject};
use minreq::Response;
@ -57,13 +70,16 @@ impl Client {
}
}
pub fn build_request(&self, request: minreq::Request) -> minreq::Request {
pub fn build_request(&self, request: minreq::Request, is_beta: bool) -> minreq::Request {
let mut request = request
.with_header("Content-Type", "application/json")
.with_header("Authorization", format!("Bearer {}", self.api_key));
if let Some(organization) = &self.organization {
request = request.with_header("openai-organization", organization);
}
if is_beta {
request = request.with_header("OpenAI-Beta", "assistants=v1");
}
request
}
@ -77,8 +93,7 @@ impl Client {
api_endpoint = self.api_endpoint,
path = path
);
let request = self.build_request(minreq::post(url));
let request = self.build_request(minreq::post(url), Self::is_beta(path));
let res = request.with_json(params).unwrap().send();
match res {
Ok(res) => {
@ -100,8 +115,7 @@ impl Client {
api_endpoint = self.api_endpoint,
path = path
);
let request = self.build_request(minreq::get(url));
let request = self.build_request(minreq::get(url), Self::is_beta(path));
let res = request.send();
match res {
Ok(res) => {
@ -123,8 +137,7 @@ impl Client {
api_endpoint = self.api_endpoint,
path = path
);
let request = self.build_request(minreq::delete(url));
let request = self.build_request(minreq::delete(url), Self::is_beta(path));
let res = request.send();
match res {
Ok(res) => {
@ -368,9 +381,396 @@ impl Client {
}
}
pub fn create_assistant(&self, req: AssistantRequest) -> Result<AssistantObject, APIError> {
let res = self.post("/assistants", &req)?;
let r = res.json::<AssistantObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_assistant(&self, assistant_id: String) -> Result<AssistantObject, APIError> {
let res = self.get(&format!("/assistants/{}", assistant_id))?;
let r = res.json::<AssistantObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn modify_assistant(
&self,
assistant_id: String,
req: AssistantRequest,
) -> Result<AssistantObject, APIError> {
let res = self.post(&format!("/assistants/{}", assistant_id), &req)?;
let r = res.json::<AssistantObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn delete_assistant(&self, assistant_id: String) -> Result<DeletionStatus, APIError> {
let res = self.delete(&format!("/assistants/{}", assistant_id))?;
let r = res.json::<DeletionStatus>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_assistant(
&self,
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
) -> Result<ListAssistant, APIError> {
let mut url = "/assistants".to_owned();
url = Self::query_params(limit, order, after, before, url);
let res = self.get(&url)?;
let r = res.json::<ListAssistant>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn create_assistant_file(
&self,
assistant_id: String,
req: AssistantFileRequest,
) -> Result<AssistantFileObject, APIError> {
let res = self.post(&format!("/assistants/{}/files", assistant_id), &req)?;
let r = res.json::<AssistantFileObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_assistant_file(
&self,
assistant_id: String,
file_id: String,
) -> Result<AssistantFileObject, APIError> {
let res = self.get(&format!("/assistants/{}/files/{}", assistant_id, file_id))?;
let r = res.json::<AssistantFileObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn delete_assistant_file(
&self,
assistant_id: String,
file_id: String,
) -> Result<DeletionStatus, APIError> {
let res = self.delete(&format!("/assistants/{}/files/{}", assistant_id, file_id))?;
let r = res.json::<DeletionStatus>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_assistant_file(
&self,
assistant_id: String,
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
) -> Result<ListAssistantFile, APIError> {
let mut url = format!("/assistants/{}/files", assistant_id);
url = Self::query_params(limit, order, after, before, url);
let res = self.get(&url)?;
let r = res.json::<ListAssistantFile>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn create_thread(&self, req: CreateThreadRequest) -> Result<ThreadObject, APIError> {
let res = self.post("/threads", &req)?;
let r = res.json::<ThreadObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_thread(&self, thread_id: String) -> Result<ThreadObject, APIError> {
let res = self.get(&format!("/threads/{}", thread_id))?;
let r = res.json::<ThreadObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn modify_thread(
&self,
thread_id: String,
req: ModifyThreadRequest,
) -> Result<ThreadObject, APIError> {
let res = self.post(&format!("/threads/{}", thread_id), &req)?;
let r = res.json::<ThreadObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn delete_thread(&self, thread_id: String) -> Result<DeletionStatus, APIError> {
let res = self.delete(&format!("/threads/{}", thread_id))?;
let r = res.json::<DeletionStatus>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn create_message(
&self,
thread_id: String,
req: CreateMessageRequest,
) -> Result<MessageObject, APIError> {
let res = self.post(&format!("/threads/{}/messages", thread_id), &req)?;
let r = res.json::<MessageObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_message(
&self,
thread_id: String,
message_id: String,
) -> Result<MessageObject, APIError> {
let res = self.get(&format!("/threads/{}/messages/{}", thread_id, message_id))?;
let r = res.json::<MessageObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn modify_message(
&self,
thread_id: String,
message_id: String,
req: ModifyMessageRequest,
) -> Result<MessageObject, APIError> {
let res = self.post(
&format!("/threads/{}/messages/{}", thread_id, message_id),
&req,
)?;
let r = res.json::<MessageObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_messages(&self, thread_id: String) -> Result<ListMessage, APIError> {
let res = self.get(&format!("/threads/{}/messages", thread_id))?;
let r = res.json::<ListMessage>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_message_file(
&self,
thread_id: String,
message_id: String,
file_id: String,
) -> Result<MessageFileObject, APIError> {
let res = self.get(&format!(
"/threads/{}/messages/{}/files/{}",
thread_id, message_id, file_id
))?;
let r = res.json::<MessageFileObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_message_file(
&self,
thread_id: String,
message_id: String,
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
) -> Result<ListMessageFile, APIError> {
let mut url = format!("/threads/{}/messages/{}/files", thread_id, message_id);
url = Self::query_params(limit, order, after, before, url);
let res = self.get(&url)?;
let r = res.json::<ListMessageFile>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn create_run(
&self,
thread_id: String,
req: CreateRunRequest,
) -> Result<RunObject, APIError> {
let res = self.post(&format!("/threads/{}/runs", thread_id), &req)?;
let r = res.json::<RunObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_run(&self, thread_id: String, run_id: String) -> Result<RunObject, APIError> {
let res = self.get(&format!("/threads/{}/runs/{}", thread_id, run_id))?;
let r = res.json::<RunObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn modify_run(
&self,
thread_id: String,
run_id: String,
req: ModifyRunRequest,
) -> Result<RunObject, APIError> {
let res = self.post(&format!("/threads/{}/runs/{}", thread_id, run_id), &req)?;
let r = res.json::<RunObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_run(
&self,
thread_id: String,
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
) -> Result<ListRun, APIError> {
let mut url = format!("/threads/{}/runs", thread_id);
url = Self::query_params(limit, order, after, before, url);
let res = self.get(&url)?;
let r = res.json::<ListRun>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn cancel_run(&self, thread_id: String, run_id: String) -> Result<RunObject, APIError> {
let empty_req = ModifyRunRequest::new();
let res = self.post(
&format!("/threads/{}/runs/{}/cancel", thread_id, run_id),
&empty_req,
)?;
let r = res.json::<RunObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn create_thread_and_run(
&self,
req: CreateThreadAndRunRequest,
) -> Result<RunObject, APIError> {
let res = self.post("/threads/runs", &req)?;
let r = res.json::<RunObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn retrieve_run_step(
&self,
thread_id: String,
run_id: String,
step_id: String,
) -> Result<RunStepObject, APIError> {
let res = self.get(&format!(
"/threads/{}/runs/{}/steps/{}",
thread_id, run_id, step_id
))?;
let r = res.json::<RunStepObject>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
pub fn list_run_step(
&self,
thread_id: String,
run_id: String,
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
) -> Result<ListRunStep, APIError> {
let mut url = format!("/threads/{}/runs/{}/steps", thread_id, run_id);
url = Self::query_params(limit, order, after, before, url);
let res = self.get(&url)?;
let r = res.json::<ListRunStep>();
match r {
Ok(r) => Ok(r),
Err(e) => Err(self.new_error(e)),
}
}
fn new_error(&self, err: minreq::Error) -> APIError {
APIError {
message: err.to_string(),
}
}
fn is_beta(path: &str) -> bool {
path.starts_with("/assistants") || path.starts_with("/threads")
}
fn query_params(
limit: Option<i64>,
order: Option<String>,
after: Option<String>,
before: Option<String>,
mut url: String,
) -> String {
let mut params = vec![];
if let Some(limit) = limit {
params.push(format!("limit={}", limit));
}
if let Some(order) = order {
params.push(format!("order={}", order));
}
if let Some(after) = after {
params.push(format!("after={}", after));
}
if let Some(before) = before {
params.push(format!("before={}", before));
}
if !params.is_empty() {
url = format!("{}?{}", url, params.join("&"));
}
url
}
}

94
src/v1/assistant.rs Normal file
View File

@ -0,0 +1,94 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::impl_builder_methods;
#[derive(Debug, Serialize, Clone)]
pub struct AssistantRequest {
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<HashMap<String, String>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl AssistantRequest {
pub fn new(model: String) -> Self {
Self {
model,
name: None,
description: None,
instructions: None,
tools: None,
file_ids: None,
metadata: None,
}
}
}
impl_builder_methods!(
AssistantRequest,
name: String,
description: String,
instructions: String,
tools: Vec<HashMap<String, String>>,
file_ids: Vec<String>,
metadata: HashMap<String, String>
);
#[derive(Debug, Serialize, Deserialize)]
pub struct AssistantObject {
pub id: String,
pub object: String,
pub created_at: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
pub tools: Vec<String>,
pub file_ids: Vec<String>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DeletionStatus {
pub id: String,
pub object: String,
pub deleted: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ListAssistant {
pub object: String,
pub data: Vec<AssistantObject>,
}
#[derive(Debug, Serialize, Clone)]
pub struct AssistantFileRequest {
pub file_id: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AssistantFileObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub assistant_id: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ListAssistantFile {
pub object: String,
pub data: Vec<AssistantFileObject>,
}

View File

@ -4,7 +4,7 @@ use crate::impl_builder_methods;
pub const WHISPER_1: &str = "whisper-1";
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct AudioTranscriptionRequest {
pub file: String,
pub model: String,
@ -44,7 +44,7 @@ pub struct AudioTranscriptionResponse {
pub text: String,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct AudioTranslationRequest {
pub file: String,
pub model: String,

View File

@ -6,35 +6,14 @@ use std::collections::HashMap;
use crate::impl_builder_methods;
use crate::v1::common;
// https://platform.openai.com/docs/models/gpt-3-5
pub const GPT3_5_TURBO_1106: &str = "gpt-3.5-turbo-1106";
pub const GPT3_5_TURBO: &str = "gpt-3.5-turbo";
pub const GPT3_5_TURBO_16K: &str = "gpt-3.5-turbo-16k";
pub const GPT3_5_TURBO_INSTRUCT: &str = "gpt-3.5-turbo-instruct";
// - legacy
pub const GPT3_5_TURBO_0613: &str = "gpt-3.5-turbo-0613";
pub const GPT3_5_TURBO_16K_0613: &str = "gpt-3.5-turbo-16k-0613";
pub const GPT3_5_TURBO_0301: &str = "gpt-3.5-turbo-0301";
// https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo
pub const GPT4_1106_PREVIEW: &str = "gpt-4-1106-preview";
pub const GPT4_VISION_PREVIEW: &str = "gpt-4-vision-preview";
pub const GPT4: &str = "gpt-4";
pub const GPT4_32K: &str = "gpt-4-32k";
pub const GPT4_0613: &str = "gpt-4-0613";
pub const GPT4_32K_0613: &str = "gpt-4-32k-0613";
// - legacy
pub const GPT4_0314: &str = "gpt-4-0314";
pub const GPT4_32K_0314: &str = "gpt-4-32k-0314";
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub enum FunctionCallType {
None,
Auto,
Function { name: String },
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct ChatCompletionRequest {
pub model: String,
pub messages: Vec<ChatCompletionMessage>,
@ -153,7 +132,7 @@ pub struct ChatCompletionResponse {
pub usage: common::Usage,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Function {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
@ -161,7 +140,7 @@ pub struct Function {
pub parameters: FunctionParameters,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum JSONSchemaType {
Object,
@ -172,7 +151,7 @@ pub enum JSONSchemaType {
Boolean,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct JSONSchemaDefine {
#[serde(rename = "type")]
pub schema_type: Option<JSONSchemaType>,
@ -188,7 +167,7 @@ pub struct JSONSchemaDefine {
pub items: Option<Box<JSONSchemaDefine>>,
}
#[derive(Debug, Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FunctionParameters {
#[serde(rename = "type")]
pub schema_type: JSONSchemaType,

View File

@ -20,3 +20,24 @@ macro_rules! impl_builder_methods {
}
};
}
// https://platform.openai.com/docs/models/gpt-3-5
pub const GPT3_5_TURBO_1106: &str = "gpt-3.5-turbo-1106";
pub const GPT3_5_TURBO: &str = "gpt-3.5-turbo";
pub const GPT3_5_TURBO_16K: &str = "gpt-3.5-turbo-16k";
pub const GPT3_5_TURBO_INSTRUCT: &str = "gpt-3.5-turbo-instruct";
// - legacy
pub const GPT3_5_TURBO_0613: &str = "gpt-3.5-turbo-0613";
pub const GPT3_5_TURBO_16K_0613: &str = "gpt-3.5-turbo-16k-0613";
pub const GPT3_5_TURBO_0301: &str = "gpt-3.5-turbo-0301";
// https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo
pub const GPT4_1106_PREVIEW: &str = "gpt-4-1106-preview";
pub const GPT4_VISION_PREVIEW: &str = "gpt-4-vision-preview";
pub const GPT4: &str = "gpt-4";
pub const GPT4_32K: &str = "gpt-4-32k";
pub const GPT4_0613: &str = "gpt-4-0613";
pub const GPT4_32K_0613: &str = "gpt-4-32k-0613";
// - legacy
pub const GPT4_0314: &str = "gpt-4-0314";
pub const GPT4_32K_0314: &str = "gpt-4-32k-0314";

View File

@ -18,7 +18,7 @@ pub const GPT3_CURIE: &str = "curie";
pub const GPT3_ADA: &str = "ada";
pub const GPT3_BABBAGE: &str = "babbage";
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct CompletionRequest {
pub model: String,
pub prompt: String,

View File

@ -4,7 +4,7 @@ use std::option::Option;
use crate::impl_builder_methods;
use crate::v1::common;
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct EditRequest {
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]

View File

@ -10,7 +10,7 @@ pub struct EmbeddingData {
pub index: i32,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct EmbeddingRequest {
pub model: String,
pub input: String,

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use crate::impl_builder_methods;
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct CreateFineTuneRequest {
pub training_file: String,
#[serde(skip_serializing_if = "Option::is_none")]

View File

@ -8,7 +8,7 @@ pub struct ImageData {
pub url: String,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct ImageGenerationRequest {
pub prompt: String,
#[serde(skip_serializing_if = "Option::is_none")]
@ -47,7 +47,7 @@ pub struct ImageGenerationResponse {
pub data: Vec<ImageData>,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct ImageEditRequest {
pub image: String,
#[serde(skip_serializing_if = "Option::is_none")]
@ -92,7 +92,7 @@ pub struct ImageEditResponse {
pub data: Vec<ImageData>,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct ImageVariationRequest {
pub image: String,
#[serde(skip_serializing_if = "Option::is_none")]

118
src/v1/message.rs Normal file
View File

@ -0,0 +1,118 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::impl_builder_methods;
#[derive(Debug, Serialize, Clone)]
pub struct CreateMessageRequest {
pub role: MessageRole,
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl CreateMessageRequest {
pub fn new(role: MessageRole, content: String) -> Self {
Self {
role,
content,
file_ids: None,
metadata: None,
}
}
}
impl_builder_methods!(
CreateMessageRequest,
file_ids: Vec<String>,
metadata: HashMap<String, String>
);
#[derive(Debug, Serialize, Clone)]
pub struct ModifyMessageRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl ModifyMessageRequest {
pub fn new() -> Self {
Self { metadata: None }
}
}
impl Default for ModifyMessageRequest {
fn default() -> Self {
Self::new()
}
}
impl_builder_methods!(
ModifyMessageRequest,
metadata: HashMap<String, String>
);
#[derive(Debug, Deserialize)]
pub struct MessageObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub thread_id: String,
pub role: MessageRole,
pub content: Vec<Content>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assistant_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub run_id: Option<String>,
pub file_ids: Vec<String>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[allow(non_camel_case_types)]
pub enum MessageRole {
user,
system,
assistant,
function,
}
#[derive(Debug, Deserialize)]
pub struct Content {
#[serde(rename = "type")]
pub content_type: String,
pub text: ContentText,
}
#[derive(Debug, Deserialize)]
pub struct ContentText {
pub value: String,
pub annotations: Vec<String>,
}
#[derive(Debug, Deserialize)]
pub struct ListMessage {
pub object: String,
pub data: Vec<MessageObject>,
pub first_id: String,
pub last_id: String,
pub has_more: bool,
}
#[derive(Debug, Deserialize)]
pub struct MessageFileObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub message_id: String,
}
#[derive(Debug, Deserialize)]
pub struct ListMessageFile {
pub object: String,
pub data: Vec<MessageFileObject>,
pub first_id: String,
pub last_id: String,
pub has_more: bool,
}

View File

@ -11,4 +11,10 @@ pub mod fine_tune;
pub mod image;
pub mod moderation;
// beta
pub mod assistant;
pub mod message;
pub mod run;
pub mod thread;
pub mod api;

View File

@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use crate::impl_builder_methods;
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub struct CreateModerationRequest {
pub input: String,
#[serde(skip_serializing_if = "Option::is_none")]

150
src/v1/run.rs Normal file
View File

@ -0,0 +1,150 @@
use super::thread::CreateThreadRequest;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::impl_builder_methods;
#[derive(Debug, Serialize, Clone)]
pub struct CreateRunRequest {
assistant_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<HashMap<String, String>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl CreateRunRequest {
pub fn new(assistant_id: String) -> Self {
Self {
assistant_id,
model: None,
instructions: None,
tools: None,
metadata: None,
}
}
}
impl_builder_methods!(
CreateRunRequest,
model: String,
instructions: String,
tools: Vec<HashMap<String, String>>,
metadata: HashMap<String, String>
);
#[derive(Debug, Serialize, Clone)]
pub struct ModifyRunRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl ModifyRunRequest {
pub fn new() -> Self {
Self { metadata: None }
}
}
impl Default for ModifyRunRequest {
fn default() -> Self {
Self::new()
}
}
impl_builder_methods!(
ModifyRunRequest,
metadata: HashMap<String, String>
);
#[derive(Debug, Deserialize)]
pub struct RunObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub thread_id: String,
pub assistant_id: String,
pub status: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub required_action: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub started_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cancelled_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub failed_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completed_at: Option<i64>,
pub model: String,
pub instructions: Option<String>,
pub tools: Vec<HashMap<String, String>>,
pub file_ids: Vec<String>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Deserialize)]
pub struct ListRun {
pub object: String,
pub data: Vec<RunObject>,
pub first_id: String,
pub last_id: String,
pub has_more: bool,
}
#[derive(Debug, Serialize, Clone)]
pub struct CreateThreadAndRunRequest {
pub assistant_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread: Option<CreateThreadRequest>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<HashMap<String, String>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct RunStepObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub assistant_id: String,
pub thread_id: String,
pub run_id: String,
#[serde(rename = "type")]
pub run_step_type: String,
pub status: String,
pub step_details: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub started_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cancelled_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub failed_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completed_at: Option<i64>,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct ListRunStep {
pub object: String,
pub data: Vec<RunStepObject>,
pub first_id: String,
pub last_id: String,
pub has_more: bool,
}

83
src/v1/thread.rs Normal file
View File

@ -0,0 +1,83 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::impl_builder_methods;
#[derive(Debug, Serialize, Clone)]
pub struct CreateThreadRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub messages: Option<Vec<Message>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl CreateThreadRequest {
pub fn new() -> Self {
Self {
messages: None,
metadata: None,
}
}
}
impl Default for CreateThreadRequest {
fn default() -> Self {
Self::new()
}
}
impl_builder_methods!(
CreateThreadRequest,
messages: Vec<Message>,
metadata: HashMap<String, String>
);
#[derive(Debug, Serialize, Deserialize)]
pub struct ThreadObject {
pub id: String,
pub object: String,
pub created_at: i64,
pub metadata: HashMap<String, String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Message {
pub role: MessageRole,
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_ids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[allow(non_camel_case_types)]
pub enum MessageRole {
user,
system,
assistant,
function,
}
#[derive(Debug, Serialize, Clone)]
pub struct ModifyThreadRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
}
impl ModifyThreadRequest {
pub fn new() -> Self {
Self { metadata: None }
}
}
impl Default for ModifyThreadRequest {
fn default() -> Self {
Self::new()
}
}
impl_builder_methods!(
ModifyThreadRequest,
metadata: HashMap<String, String>
);