From 35d9cdaf0c1600e4edad884ef269215266d5392a Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 16:48:58 -0700
Subject: [PATCH 01/21] CreateChatCompletionRequest updated

---
 async-openai/src/types/chat.rs | 51 +++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index 2dc65d16..b81239da 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -308,23 +308,31 @@ pub struct FunctionObject {
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
-#[serde(rename_all = "snake_case")]
-pub enum ChatCompletionResponseFormatType {
+#[serde(tag = "type", rename_all = "snake_case")]
+pub enum ChatCompletionResponseFormat {
+    /// The type of response format being defined: `text`
     Text,
+    /// The type of response format being defined: `json_object`
     JsonObject,
+    /// The type of response format being defined: `json_schema`
+    JsonSchema {
+        json_schema: ChatCompletionResponseFormatJsonSchema,
+    },
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
-pub struct ChatCompletionResponseFormat {
-    /// Setting to `json_object` enables JSON mode. This guarantees that the message the model generates is valid JSON.
-    ///
-    /// Note that your system prompt must still instruct the model to produce JSON, and to help ensure you don't forget,
-    /// the API will throw an error if the string `JSON` does not appear in your system message. Also note that the message
-    /// content may be partial (i.e. cut off) if `finish_reason="length"`, which indicates the generation
-    /// exceeded `max_tokens` or the conversation exceeded the max context length.
-    ///
-    /// Must be one of `text` or `json_object`.
-    pub r#type: ChatCompletionResponseFormatType,
+pub struct ChatCompletionResponseFormatJsonSchema {
+    /// A description of what the response format is for, used by the model to determine how to respond in the format.
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub description: Option<String>,
+    /// The name of the response format. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length
+    pub name: String,
+    /// The schema for the response format, described as a JSON Schema object.
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub schema: Option<serde_json::Value>,
+    /// Whether to enable strict schema adherence when generating the output. If set to true, the model will always follow the exact schema defined in the `schema` field. Only a subset of JSON Schema is supported when `strict` is `true`. To learn more, read the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs).
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub strict: Option<bool>,
 }
 
 #[derive(Clone, Serialize, Default, Debug, Deserialize, PartialEq)]
@@ -379,6 +387,13 @@ pub enum ChatCompletionToolChoiceOption {
     Named(ChatCompletionNamedToolChoice),
 }
 
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum ServiceTier {
+    Auto,
+    Default,
+}
+
 #[derive(Clone, Serialize, Default, Debug, Builder, Deserialize, PartialEq)]
 #[builder(name = "CreateChatCompletionRequestArgs")]
 #[builder(pattern = "mutable")]
@@ -432,7 +447,9 @@ pub struct CreateChatCompletionRequest {
     #[serde(skip_serializing_if = "Option::is_none")]
     pub presence_penalty: Option<f32>, // min: -2.0, max: 2.0, default 0
 
-    /// An object specifying the format that the model must output. Compatible with [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo) and all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`.
+    /// An object specifying the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models/gpt-4o), [GPT-4o mini](https://platform.openai.com/docs/models/gpt-4o-mini), [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo) and all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`.
+    ///
+    /// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which guarantees the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs).
     ///
     /// Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON.
     ///
@@ -447,6 +464,14 @@ pub struct CreateChatCompletionRequest {
     #[serde(skip_serializing_if = "Option::is_none")]
     pub seed: Option<i64>,
 
+    /// Specifies the latency tier to use for processing the request. This parameter is relevant for customers subscribed to the scale tier service:
+    /// - If set to 'auto', the system will utilize scale tier credits until they are exhausted.
+    /// - If set to 'default', the request will be processed using the default service tier with a lower uptime SLA and no latency guarentee.
+    /// - When not set, the default behavior is 'auto'.
+    ///
+    /// When this parameter is set, the response body will include the `service_tier` utilized.
+    pub service_tier: Option<ServiceTier>,
+
     /// Up to 4 sequences where the API will stop generating further tokens.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub stop: Option<Stop>,

From 793b988b9580fb5975f864032f0c5ba7745e698e Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 17:01:47 -0700
Subject: [PATCH 02/21] CreateChatCompletionResponse updated

---
 async-openai/src/types/chat.rs | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index b81239da..5ebbfa98 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -256,7 +256,8 @@ pub struct ChatCompletionMessageToolCall {
 pub struct ChatCompletionResponseMessage {
     /// The contents of the message.
     pub content: Option<String>,
-
+    /// The refusal message generated by the model.
+    pub refusal: Option<String>,
     /// The tool calls generated by the model, such as function calls.
     pub tool_calls: Option<Vec<ChatCompletionMessageToolCall>>,
 
@@ -394,6 +395,13 @@ pub enum ServiceTier {
     Default,
 }
 
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum ServiceTierResponse {
+    Scale,
+    Default,
+}
+
 #[derive(Clone, Serialize, Default, Debug, Builder, Deserialize, PartialEq)]
 #[builder(name = "CreateChatCompletionRequestArgs")]
 #[builder(pattern = "mutable")]
@@ -579,6 +587,7 @@ pub struct ChatCompletionTokenLogprob {
 pub struct ChatChoiceLogprobs {
     /// A list of message content tokens with log probability information.
     pub content: Option<Vec<ChatCompletionTokenLogprob>>,
+    pub refusal: Option<Vec<ChatCompletionTokenLogprob>>,
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
@@ -606,6 +615,8 @@ pub struct CreateChatCompletionResponse {
     pub created: u32,
     /// The model used for the chat completion.
     pub model: String,
+    /// he service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request.
+    pub service_tier: Option<ServiceTierResponse>,
     /// This fingerprint represents the backend configuration that the model runs with.
     ///
     /// Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.

From 6581945f7b6abeea8e663ede25db8fcd18e326a0 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 17:04:51 -0700
Subject: [PATCH 03/21] ChatCompletionStreamResponseDelta updated

---
 async-openai/src/types/chat.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index 5ebbfa98..e300e561 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -664,6 +664,8 @@ pub struct ChatCompletionStreamResponseDelta {
     pub tool_calls: Option<Vec<ChatCompletionMessageToolCallChunk>>,
     /// The role of the author of this message.
     pub role: Option<Role>,
+    /// The refusal message generated by the model.
+    pub refusal: Option<String>,
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]

From e73fe7e78e04ffbd3f25247d0636ae449876e47e Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 17:07:12 -0700
Subject: [PATCH 04/21] CreateChatCompletionStreamResponse updated

---
 async-openai/src/types/chat.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index e300e561..186d084c 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -615,7 +615,7 @@ pub struct CreateChatCompletionResponse {
     pub created: u32,
     /// The model used for the chat completion.
     pub model: String,
-    /// he service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request.
+    /// The service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request.
     pub service_tier: Option<ServiceTierResponse>,
     /// This fingerprint represents the backend configuration that the model runs with.
     ///
@@ -690,6 +690,8 @@ pub struct CreateChatCompletionStreamResponse {
     pub created: u32,
     /// The model to generate the completion.
     pub model: String,
+    /// The service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request.
+    pub service_tier: Option<ServiceTierResponse>,
     /// This fingerprint represents the backend configuration that the model runs with.
     /// Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.
     pub system_fingerprint: Option<String>,

From e4100e4eb889cde947ed87cf2e4165558347a124 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 21:58:27 -0700
Subject: [PATCH 05/21] CreateFineTuningJobRequest updated

---
 async-openai/src/types/fine_tuning.rs | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/async-openai/src/types/fine_tuning.rs b/async-openai/src/types/fine_tuning.rs
index ae9af2c7..e4cf6246 100644
--- a/async-openai/src/types/fine_tuning.rs
+++ b/async-openai/src/types/fine_tuning.rs
@@ -12,8 +12,32 @@ pub enum NEpochs {
     Auto,
 }
 
+#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
+#[serde(untagged)]
+pub enum BatchSize {
+    BatchSize(u16),
+    #[default]
+    #[serde(rename = "auto")]
+    Auto,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
+#[serde(untagged)]
+pub enum LearningRateMultiplier {
+    LearningRateMultiplier(f32),
+    #[default]
+    #[serde(rename = "auto")]
+    Auto,
+}
+
 #[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)]
 pub struct Hyperparameters {
+    /// Number of examples in each batch. A larger batch size means that model parameters
+    /// are updated less frequently, but with lower variance.
+    pub batch_size: BatchSize,
+    /// Scaling factor for the learning rate. A smaller learning rate may be useful to avoid
+    /// overfitting.
+    pub learning_rate_multiplier: LearningRateMultiplier,
     /// The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.
     pub n_epochs: NEpochs,
 }
@@ -46,7 +70,7 @@ pub struct CreateFineTuningJobRequest {
     /// A string of up to 18 characters that will be added to your fine-tuned model name.
     ///
     /// For example, a `suffix` of "custom-model-name" would produce a model name
-    /// like `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`.
+    /// like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub suffix: Option<String>, // default: null, minLength:1, maxLength:40
 

From 26758548d07f2711d3ab748d19d5d6afd95bec88 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 22:22:40 -0700
Subject: [PATCH 06/21] ResponseFormat and ImageResponseFormat

---
 async-openai/README.md              |  8 +++++---
 async-openai/src/types/assistant.rs | 23 ++++-------------------
 async-openai/src/types/chat.rs      |  8 ++++----
 async-openai/src/types/image.rs     |  8 ++++----
 async-openai/src/types/impls.rs     | 10 +++++-----
 5 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/async-openai/README.md b/async-openai/README.md
index 4ab25a6b..4ef02579 100644
--- a/async-openai/README.md
+++ b/async-openai/README.md
@@ -61,7 +61,7 @@ $Env:OPENAI_API_KEY='sk-...'
 
 ```rust
 use async_openai::{
-    types::{CreateImageRequestArgs, ImageSize, ResponseFormat},
+    types::{CreateImageRequestArgs, ImageSize, ImageResponseFormat},
     Client,
 };
 use std::error::Error;
@@ -74,7 +74,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
     let request = CreateImageRequestArgs::default()
         .prompt("cats on sofa and carpet in living room")
         .n(2)
-        .response_format(ResponseFormat::Url)
+        .response_format(ImageResponseFormat::Url)
         .size(ImageSize::S256x256)
         .user("async-openai")
         .build()?;
@@ -110,14 +110,16 @@ All forms of contributions, such as new features requests, bug fixes, issues, do
 A good starting point would be to look at existing [open issues](https://github.com/64bit/async-openai/issues).
 
 To maintain quality of the project, a minimum of the following is a must for code contribution:
+
 - **Names & Documentation**: All struct names, field names and doc comments are from OpenAPI spec. Nested objects in spec without names leaves room for making appropriate name.
-- **Tested**:  For changes supporting test(s) and/or example is required. Existing examples, doc tests, unit tests, and integration tests should be made to work with the changes if applicable.
+- **Tested**: For changes supporting test(s) and/or example is required. Existing examples, doc tests, unit tests, and integration tests should be made to work with the changes if applicable.
 - **Scope**: Keep scope limited to APIs available in official documents such as [API Reference](https://platform.openai.com/docs/api-reference) or [OpenAPI spec](https://github.com/openai/openai-openapi/). Other LLMs or AI Providers offer OpenAI-compatible APIs, yet they may not always have full parity. In such cases, the OpenAI spec takes precedence.
 - **Consistency**: Keep code style consistent across all the "APIs" that library exposes; it creates a great developer experience.
 
 This project adheres to [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct)
 
 ## Complimentary Crates
+
 - [openai-func-enums](https://github.com/frankfralick/openai-func-enums) provides procedural macros that make it easier to use this library with OpenAI API's tool calling feature. It also provides derive macros you can add to existing [clap](https://github.com/clap-rs/clap) application subcommands for natural language use of command line tools. It also supports openai's [parallel tool calls](https://platform.openai.com/docs/guides/function-calling/parallel-function-calling) and allows you to choose between running multiple tool calls concurrently or own their own OS threads.
 - [async-openai-wasm](https://github.com/ifsheldon/async-openai-wasm) provides WASM support.
 
diff --git a/async-openai/src/types/assistant.rs b/async-openai/src/types/assistant.rs
index 2abc42b7..bc157b7c 100644
--- a/async-openai/src/types/assistant.rs
+++ b/async-openai/src/types/assistant.rs
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
 
 use crate::error::OpenAIError;
 
-use super::{FunctionName, FunctionObject};
+use super::{FunctionName, FunctionObject, ResponseFormat};
 
 #[derive(Clone, Serialize, Debug, Deserialize, PartialEq, Default)]
 pub struct AssistantToolCodeInterpreterResources {
@@ -112,6 +112,8 @@ pub struct AssistantObject {
 
 /// Specifies the format that the model must output. Compatible with [GPT-4o](https://platform.openai.com/docs/models/gpt-4o), [GPT-4 Turbo](https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`.
 ///
+/// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which guarantees the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs).
+///
 /// Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON.
 ///
 /// **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.
@@ -120,25 +122,8 @@ pub enum AssistantsApiResponseFormatOption {
     #[default]
     #[serde(rename = "auto")]
     Auto,
-    #[serde(rename = "none")]
-    None,
     #[serde(untagged)]
-    Format(AssistantsApiResponseFormat),
-}
-
-/// An object describing the expected output of the model. If `json_object` only `function` type `tools` are allowed to be passed to the Run. If `text` the model can return text or any value needed.
-#[derive(Clone, Serialize, Debug, Deserialize, PartialEq, Default)]
-pub struct AssistantsApiResponseFormat {
-    /// Must be one of `text` or `json_object`.
-    pub r#type: AssistantsApiResponseFormatType,
-}
-
-#[derive(Clone, Serialize, Debug, Deserialize, PartialEq, Default)]
-#[serde(rename_all = "snake_case")]
-pub enum AssistantsApiResponseFormatType {
-    #[default]
-    Text,
-    JsonObject,
+    Format(ResponseFormat),
 }
 
 /// Retrieval tool
diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index 186d084c..dda586d7 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -310,19 +310,19 @@ pub struct FunctionObject {
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
 #[serde(tag = "type", rename_all = "snake_case")]
-pub enum ChatCompletionResponseFormat {
+pub enum ResponseFormat {
     /// The type of response format being defined: `text`
     Text,
     /// The type of response format being defined: `json_object`
     JsonObject,
     /// The type of response format being defined: `json_schema`
     JsonSchema {
-        json_schema: ChatCompletionResponseFormatJsonSchema,
+        json_schema: ResponseFormatJsonSchema,
     },
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
-pub struct ChatCompletionResponseFormatJsonSchema {
+pub struct ResponseFormatJsonSchema {
     /// A description of what the response format is for, used by the model to determine how to respond in the format.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub description: Option<String>,
@@ -463,7 +463,7 @@ pub struct CreateChatCompletionRequest {
     ///
     /// **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.
     #[serde(skip_serializing_if = "Option::is_none")]
-    pub response_format: Option<ChatCompletionResponseFormat>,
+    pub response_format: Option<ResponseFormat>,
 
     ///  This feature is in Beta.
     /// If specified, our system will make a best effort to sample deterministically, such that repeated requests
diff --git a/async-openai/src/types/image.rs b/async-openai/src/types/image.rs
index d1bcf6be..86169c46 100644
--- a/async-openai/src/types/image.rs
+++ b/async-openai/src/types/image.rs
@@ -33,7 +33,7 @@ pub enum DallE2ImageSize {
 
 #[derive(Debug, Serialize, Deserialize, Default, Clone, Copy, PartialEq)]
 #[serde(rename_all = "lowercase")]
-pub enum ResponseFormat {
+pub enum ImageResponseFormat {
     #[default]
     Url,
     #[serde(rename = "b64_json")]
@@ -93,7 +93,7 @@ pub struct CreateImageRequest {
 
     /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated.
     #[serde(skip_serializing_if = "Option::is_none")]
-    pub response_format: Option<ResponseFormat>,
+    pub response_format: Option<ImageResponseFormat>,
 
     /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`.
     /// Must be one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3` models.
@@ -164,7 +164,7 @@ pub struct CreateImageEditRequest {
     pub size: Option<DallE2ImageSize>,
 
     /// The format in which the generated images are returned. Must be one of `url` or `b64_json`.
-    pub response_format: Option<ResponseFormat>,
+    pub response_format: Option<ImageResponseFormat>,
 
     /// A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/usage-policies/end-user-ids).
     pub user: Option<String>,
@@ -190,7 +190,7 @@ pub struct CreateImageVariationRequest {
     pub size: Option<DallE2ImageSize>,
 
     /// The format in which the generated images are returned. Must be one of `url` or `b64_json`.
-    pub response_format: Option<ResponseFormat>,
+    pub response_format: Option<ImageResponseFormat>,
 
     /// A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse. [Learn more](https://platform.openai.com/docs/usage-policies/end-user-ids).
     pub user: Option<String>,
diff --git a/async-openai/src/types/impls.rs b/async-openai/src/types/impls.rs
index 925f8fb4..581683b2 100644
--- a/async-openai/src/types/impls.rs
+++ b/async-openai/src/types/impls.rs
@@ -22,8 +22,8 @@ use super::{
     ChatCompletionRequestUserMessageContent, ChatCompletionToolChoiceOption, CreateFileRequest,
     CreateImageEditRequest, CreateImageVariationRequest, CreateMessageRequestContent,
     CreateSpeechResponse, CreateTranscriptionRequest, CreateTranslationRequest, DallE2ImageSize,
-    EmbeddingInput, FileInput, FilePurpose, FunctionName, Image, ImageInput, ImageModel, ImageSize,
-    ImageUrl, ImagesResponse, ModerationInput, Prompt, ResponseFormat, Role, Stop,
+    EmbeddingInput, FileInput, FilePurpose, FunctionName, Image, ImageInput, ImageModel,
+    ImageResponseFormat, ImageSize, ImageUrl, ImagesResponse, ModerationInput, Prompt, Role, Stop,
     TimestampGranularity,
 };
 
@@ -200,14 +200,14 @@ impl Display for ImageModel {
     }
 }
 
-impl Display for ResponseFormat {
+impl Display for ImageResponseFormat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
             "{}",
             match self {
-                ResponseFormat::Url => "url",
-                ResponseFormat::B64Json => "b64_json",
+                Self::Url => "url",
+                Self::B64Json => "b64_json",
             }
         )
     }

From c6c33342644222008e5e417a74f718c1184162cb Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 22:23:01 -0700
Subject: [PATCH 07/21] update examples with ImageResponseFormat

---
 examples/create-image-b64-json/src/main.rs  | 4 ++--
 examples/create-image-edit/src/main.rs      | 4 ++--
 examples/create-image-variation/src/main.rs | 4 ++--
 examples/create-image/src/main.rs           | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/examples/create-image-b64-json/src/main.rs b/examples/create-image-b64-json/src/main.rs
index a552126d..3cae2396 100644
--- a/examples/create-image-b64-json/src/main.rs
+++ b/examples/create-image-b64-json/src/main.rs
@@ -1,5 +1,5 @@
 use async_openai::{
-    types::{CreateImageRequestArgs, ImageSize, ResponseFormat},
+    types::{CreateImageRequestArgs, ImageResponseFormat, ImageSize},
     Client,
 };
 use std::error::Error;
@@ -12,7 +12,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
     let request = CreateImageRequestArgs::default()
         .prompt("Generate a logo for github repository async-openai")
         .n(2)
-        .response_format(ResponseFormat::B64Json)
+        .response_format(ImageResponseFormat::B64Json)
         .size(ImageSize::S256x256)
         .user("async-openai")
         .build()?;
diff --git a/examples/create-image-edit/src/main.rs b/examples/create-image-edit/src/main.rs
index 7c0fbf24..20e96735 100644
--- a/examples/create-image-edit/src/main.rs
+++ b/examples/create-image-edit/src/main.rs
@@ -1,5 +1,5 @@
 use async_openai::{
-    types::{CreateImageEditRequestArgs, DallE2ImageSize, ResponseFormat},
+    types::{CreateImageEditRequestArgs, DallE2ImageSize, ImageResponseFormat},
     Client,
 };
 use std::error::Error;
@@ -14,7 +14,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
         .prompt("A sunlit indoor lounge area with a duck in the pool")
         .n(1)
         .size(DallE2ImageSize::S1024x1024)
-        .response_format(ResponseFormat::Url)
+        .response_format(ImageResponseFormat::Url)
         .user("async-openai")
         .build()?;
 
diff --git a/examples/create-image-variation/src/main.rs b/examples/create-image-variation/src/main.rs
index 5e0615c7..e0244fec 100644
--- a/examples/create-image-variation/src/main.rs
+++ b/examples/create-image-variation/src/main.rs
@@ -1,5 +1,5 @@
 use async_openai::{
-    types::{CreateImageVariationRequestArgs, DallE2ImageSize, ResponseFormat},
+    types::{CreateImageVariationRequestArgs, DallE2ImageSize, ImageResponseFormat},
     Client,
 };
 use std::error::Error;
@@ -12,7 +12,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
         .image("./images/cake.png")
         .n(1)
         .size(DallE2ImageSize::S512x512)
-        .response_format(ResponseFormat::Url)
+        .response_format(ImageResponseFormat::Url)
         .user("async-openai")
         .build()?;
 
diff --git a/examples/create-image/src/main.rs b/examples/create-image/src/main.rs
index 7bc6064c..5de3467a 100644
--- a/examples/create-image/src/main.rs
+++ b/examples/create-image/src/main.rs
@@ -1,5 +1,5 @@
 use async_openai::{
-    types::{CreateImageRequestArgs, ImageSize, ResponseFormat},
+    types::{CreateImageRequestArgs, ImageResponseFormat, ImageSize},
     Client,
 };
 use std::error::Error;
@@ -12,7 +12,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
     let request = CreateImageRequestArgs::default()
         .prompt("cats on sofa and carpet in living room")
         .n(2)
-        .response_format(ResponseFormat::Url)
+        .response_format(ImageResponseFormat::Url)
         .size(ImageSize::S256x256)
         .user("async-openai")
         .build()?;

From 30a4aa34474628dba7c1a394e5797502643138cb Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Tue, 27 Aug 2024 22:34:08 -0700
Subject: [PATCH 08/21] AssistantToolsFileSearch updated with
 FileSearchRankingOptions

---
 async-openai/src/types/assistant.rs | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/async-openai/src/types/assistant.rs b/async-openai/src/types/assistant.rs
index bc157b7c..173cc60a 100644
--- a/async-openai/src/types/assistant.rs
+++ b/async-openai/src/types/assistant.rs
@@ -138,8 +138,28 @@ pub struct AssistantToolsFileSearch {
 pub struct AssistantToolsFileSearchOverrides {
     ///  The maximum number of results the file search tool should output. The default is 20 for gpt-4* models and 5 for gpt-3.5-turbo. This number should be between 1 and 50 inclusive.
     ///
-    //// Note that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search/number-of-chunks-returned) for more information.
-    pub max_num_results: u8,
+    //// Note that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search/customizing-file-search-settings) for more information.
+    pub max_num_results: Option<u8>,
+    pub ranking_options: Option<FileSearchRankingOptions>,
+}
+
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub enum FileSearchRanker {
+    #[serde(rename = "auto")]
+    Auto,
+    #[serde(rename = "default_2024_08_21")]
+    Default2024_08_21,
+}
+
+/// The ranking options for the file search.
+///
+/// See the [file search tool documentation](/docs/assistants/tools/file-search/customizing-file-search-settings) for more information.
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct FileSearchRankingOptions {
+    /// The ranker to use for the file search. If not specified will use the `auto` ranker.
+    pub ranker: Option<FileSearchRanker>,
+    /// The score threshold for the file search. All values must be a floating point number between 0 and 1.
+    pub score_threshold: Option<f32>,
 }
 
 /// Function tool

From 18434ef4473cd7132a3beafcecda95593a008caf Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 19:40:38 -0700
Subject: [PATCH 09/21] updated MessageContent and MessageDeltaContent to
 include refusal variant

---
 async-openai/src/types/message.rs | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/async-openai/src/types/message.rs b/async-openai/src/types/message.rs
index 883f6bde..d7b6d17c 100644
--- a/async-openai/src/types/message.rs
+++ b/async-openai/src/types/message.rs
@@ -104,6 +104,12 @@ pub enum MessageContent {
     Text(MessageContentTextObject),
     ImageFile(MessageContentImageFileObject),
     ImageUrl(MessageContentImageUrlObject),
+    Refusal(MessageContentRefusalObject),
+}
+
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct MessageContentRefusalObject {
+    pub refusal: String,
 }
 
 /// The text content that is part of a message.
@@ -274,6 +280,14 @@ pub enum MessageDeltaContent {
     ImageFile(MessageDeltaContentImageFileObject),
     ImageUrl(MessageDeltaContentImageUrlObject),
     Text(MessageDeltaContentTextObject),
+    Refusal(MessageDeltaContentRefusalObject),
+}
+
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct MessageDeltaContentRefusalObject {
+    /// The index of the refusal part in the message.
+    pub index: i32,
+    pub refusal: Option<String>,
 }
 
 /// The text content that is part of a message.

From e038a30bad65b210ae9cfd9d0c55e5c7648eb771 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 19:40:55 -0700
Subject: [PATCH 10/21] update examples with message refusal variant

---
 examples/assistants-code-interpreter/src/main.rs | 3 +++
 examples/assistants-file-search/src/main.rs      | 3 +++
 examples/assistants/src/main.rs                  | 1 +
 3 files changed, 7 insertions(+)

diff --git a/examples/assistants-code-interpreter/src/main.rs b/examples/assistants-code-interpreter/src/main.rs
index 68f30017..bee370dc 100644
--- a/examples/assistants-code-interpreter/src/main.rs
+++ b/examples/assistants-code-interpreter/src/main.rs
@@ -115,6 +115,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
                             MessageContent::ImageUrl(object) => {
                                 eprintln!("Got Image URL instead: {object:?}");
                             }
+                            MessageContent::Refusal(refusal) => {
+                                println!("{refusal:?}");
+                            }
                         }
                     }
                 }
diff --git a/examples/assistants-file-search/src/main.rs b/examples/assistants-file-search/src/main.rs
index 7723fe6f..aca9731e 100644
--- a/examples/assistants-file-search/src/main.rs
+++ b/examples/assistants-file-search/src/main.rs
@@ -144,6 +144,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
                             MessageContent::ImageFile(_) | MessageContent::ImageUrl(_) => {
                                 eprintln!("Images not supported on terminal");
                             }
+                            MessageContent::Refusal(refusal) => {
+                                println!("{refusal:?}");
+                            }
                         }
                     }
                 }
diff --git a/examples/assistants/src/main.rs b/examples/assistants/src/main.rs
index 21fc3e83..eaebde24 100644
--- a/examples/assistants/src/main.rs
+++ b/examples/assistants/src/main.rs
@@ -115,6 +115,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
                         MessageContent::ImageFile(_) | MessageContent::ImageUrl(_) => {
                             panic!("imaged are not expected in this example");
                         }
+                        MessageContent::Refusal(refusal) => refusal.refusal.clone(),
                     };
                     //print the text
                     println!("--- Response: {}\n", text);

From cb8e32617dd08f2de1025b4294e1031e58b8d1ed Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 19:56:35 -0700
Subject: [PATCH 11/21] updated RunStepDetailsToolCallsFileSearchObject

---
 async-openai/src/types/step.rs | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/async-openai/src/types/step.rs b/async-openai/src/types/step.rs
index 63f1b61d..d95b3c18 100644
--- a/async-openai/src/types/step.rs
+++ b/async-openai/src/types/step.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
 
 use serde::{Deserialize, Serialize};
 
-use super::{ImageFile, LastError, RunStatus};
+use super::{FileSearchRankingOptions, ImageFile, LastError, RunStatus};
 
 #[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
 #[serde(rename_all = "snake_case")]
@@ -154,7 +154,34 @@ pub struct RunStepDetailsToolCallsFileSearchObject {
     /// The ID of the tool call object.
     pub id: String,
     /// For now, this is always going to be an empty object.
-    pub file_search: serde_json::Value,
+    pub file_search: RunStepDetailsToolCallsFileSearchObjectFileSearch,
+}
+
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct RunStepDetailsToolCallsFileSearchObjectFileSearch {
+    pub ranking_options: Option<FileSearchRankingOptions>,
+    /// The results of the file search.
+    pub results: Option<Vec<RunStepDetailsToolCallsFileSearchResultObject>>,
+}
+
+/// A result instance of the file search.
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct RunStepDetailsToolCallsFileSearchResultObject {
+    /// The ID of the file that result was found in.
+    pub file_id: String,
+    /// The name of the file that result was found in.
+    pub file_name: String,
+    /// The score of the result. All values must be a floating point number between 0 and 1.
+    pub score: f32,
+    /// The content of the result that was found. The content is only included if requested via the include query parameter.
+    pub content: Option<Vec<RunStepDetailsToolCallsFileSearchResultObjectContent>>,
+}
+
+#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
+pub struct RunStepDetailsToolCallsFileSearchResultObjectContent {
+    // note: type is text hence omitted from struct
+    /// The text content of the file.
+    pub text: Option<String>,
 }
 
 #[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]

From fafafffd471a89f4206d7a82e9aea4374139865e Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 20:10:23 -0700
Subject: [PATCH 12/21] updated VectoreStoreFileObject last_error enum variant

---
 async-openai/src/types/vector_store.rs | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/async-openai/src/types/vector_store.rs b/async-openai/src/types/vector_store.rs
index 85250f9e..7e3dea25 100644
--- a/async-openai/src/types/vector_store.rs
+++ b/async-openai/src/types/vector_store.rs
@@ -180,11 +180,9 @@ pub struct VectorStoreFileError {
 #[derive(Debug, Deserialize, Clone, PartialEq, Serialize)]
 #[serde(rename_all = "snake_case")]
 pub enum VectorStoreFileErrorCode {
-    InternalError,
-    FileNotFound,
-    ParsingError,
-    UnhandledMimeType,
+    ServerError,
     UnsupportedFile,
+    InvalidFile,
 }
 
 #[derive(Debug, Deserialize, Clone, PartialEq, Serialize)]

From 0195cef514d95c7ca74aa5a5e63b2b50c8de0e86 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 21:57:05 -0700
Subject: [PATCH 13/21] updated step-object link

---
 async-openai/src/types/assistant_stream.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/async-openai/src/types/assistant_stream.rs b/async-openai/src/types/assistant_stream.rs
index 4d7f951f..755a322d 100644
--- a/async-openai/src/types/assistant_stream.rs
+++ b/async-openai/src/types/assistant_stream.rs
@@ -66,25 +66,25 @@ pub enum AssistantStreamEvent {
     /// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) expires.
     #[serde(rename = "thread.run.expired")]
     ThreadRunExpired(RunObject),
-    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) is created.
+    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is created.
     #[serde(rename = "thread.run.step.created")]
     ThreadRunStepCreated(RunStepObject),
-    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) moves to an `in_progress` state.
+    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) moves to an `in_progress` state.
     #[serde(rename = "thread.run.step.in_progress")]
     ThreadRunStepInProgress(RunStepObject),
-    /// Occurs when parts of a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) are being streamed.
+    /// Occurs when parts of a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) are being streamed.
     #[serde(rename = "thread.run.step.delta")]
     ThreadRunStepDelta(RunStepDeltaObject),
-    ///  Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) is completed.
+    ///  Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is completed.
     #[serde(rename = "thread.run.step.completed")]
     ThreadRunStepCompleted(RunStepObject),
-    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) fails.
+    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) fails.
     #[serde(rename = "thread.run.step.failed")]
     ThreadRunStepFailed(RunStepObject),
-    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) is cancelled.
+    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) is cancelled.
     #[serde(rename = "thread.run.step.cancelled")]
     ThreadRunStepCancelled(RunStepObject),
-    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/runs/step-object) expires.
+    /// Occurs when a [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) expires.
     #[serde(rename = "thread.run.step.expired")]
     ThreadRunStepExpired(RunStepObject),
     /// Occurs when a [message](https://platform.openai.com/docs/api-reference/messages/object) is created.

From 7f116349c6fcd36c76c3d495f63a87923ca86a70 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 23:09:15 -0700
Subject: [PATCH 14/21] updated ChatCompletionRequestMessage

---
 async-openai/src/types/chat.rs  | 73 +++++++++++++++++++++++++----
 async-openai/src/types/impls.rs | 81 +++++++++++++++++++++++++++------
 2 files changed, 130 insertions(+), 24 deletions(-)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index dda586d7..f5ecee92 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -103,7 +103,7 @@ pub struct CompletionUsage {
 #[builder(build_fn(error = "OpenAIError"))]
 pub struct ChatCompletionRequestSystemMessage {
     /// The contents of the system message.
-    pub content: String,
+    pub content: ChatCompletionRequestSystemMessageContent,
     /// An optional name for the participant. Provides the model information to differentiate between participants of the same role.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub name: Option<String>,
@@ -119,6 +119,12 @@ pub struct ChatCompletionRequestMessageContentPartText {
     pub text: String,
 }
 
+#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
+pub struct ChatCompletionRequestMessageContentPartRefusal {
+    /// The refusal message generated by the model.
+    pub refusal: String,
+}
+
 #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)]
 #[serde(rename_all = "lowercase")]
 pub enum ImageDetail {
@@ -154,20 +160,67 @@ pub struct ChatCompletionRequestMessageContentPartImage {
 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
 #[serde(tag = "type")]
 #[serde(rename_all = "snake_case")]
-pub enum ChatCompletionRequestMessageContentPart {
+pub enum ChatCompletionRequestUserMessageContentPart {
     Text(ChatCompletionRequestMessageContentPartText),
     ImageUrl(ChatCompletionRequestMessageContentPartImage),
 }
 
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(tag = "type")]
+#[serde(rename_all = "snake_case")]
+pub enum ChatCompletionRequestSystemMessageContentPart {
+    Text(ChatCompletionRequestMessageContentPartText),
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(tag = "type")]
+#[serde(rename_all = "snake_case")]
+pub enum ChatCompletionRequestAssistantMessageContentPart {
+    Text(ChatCompletionRequestMessageContentPartText),
+    Refusal(ChatCompletionRequestMessageContentPartRefusal),
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(tag = "type")]
+#[serde(rename_all = "snake_case")]
+pub enum ChatCompletionRequestToolMessageContentPart {
+    Text(ChatCompletionRequestMessageContentPartText),
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(untagged)]
+pub enum ChatCompletionRequestSystemMessageContent {
+    /// The text contents of the system message.
+    Text(String),
+    /// An array of content parts with a defined type. For system messages, only type `text` is supported.
+    Array(Vec<ChatCompletionRequestSystemMessageContentPart>),
+}
+
 #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
 #[serde(untagged)]
 pub enum ChatCompletionRequestUserMessageContent {
     /// The text contents of the message.
     Text(String),
-    ///  An array of content parts with a defined type, each can be of type `text` or `image_url`
-    /// when passing in images. You can pass multiple images by adding multiple `image_url` content parts.
-    ///  Image input is only supported when using the `gpt-4-visual-preview` model.
-    Array(Vec<ChatCompletionRequestMessageContentPart>),
+    /// An array of content parts with a defined type, each can be of type `text` or `image_url` when passing in images. You can pass multiple images by adding multiple `image_url` content parts. Image input is only supported when using the `gpt-4o` model.
+    Array(Vec<ChatCompletionRequestUserMessageContentPart>),
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(untagged)]
+pub enum ChatCompletionRequestAssistantMessageContent {
+    /// The text contents of the message.
+    Text(String),
+    /// An array of content parts with a defined type. Can be one or more of type `text`, or exactly one of type `refusal`.
+    Array(Vec<ChatCompletionRequestAssistantMessageContentPart>),
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
+#[serde(untagged)]
+pub enum ChatCompletionRequestToolMessageContent {
+    /// The text contents of the tool message.
+    Text(String),
+    /// An array of content parts with a defined type. For tool messages, only type `text` is supported.
+    Array(Vec<ChatCompletionRequestToolMessageContentPart>),
 }
 
 #[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
@@ -191,8 +244,10 @@ pub struct ChatCompletionRequestUserMessage {
 #[builder(derive(Debug))]
 #[builder(build_fn(error = "OpenAIError"))]
 pub struct ChatCompletionRequestAssistantMessage {
-    /// The contents of the assistant message.
-    pub content: Option<String>,
+    /// The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified.
+    pub content: Option<ChatCompletionRequestAssistantMessageContent>,
+    /// The refusal message by the assistant.
+    pub refusal: Option<String>,
     /// An optional name for the participant. Provides the model information to differentiate between participants of the same role.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub name: Option<String>,
@@ -213,7 +268,7 @@ pub struct ChatCompletionRequestAssistantMessage {
 #[builder(build_fn(error = "OpenAIError"))]
 pub struct ChatCompletionRequestToolMessage {
     /// The contents of the tool message.
-    pub content: String,
+    pub content: ChatCompletionRequestToolMessageContent,
     pub tool_call_id: String,
 }
 
diff --git a/async-openai/src/types/impls.rs b/async-openai/src/types/impls.rs
index 581683b2..d4f0d0b3 100644
--- a/async-openai/src/types/impls.rs
+++ b/async-openai/src/types/impls.rs
@@ -15,16 +15,17 @@ use bytes::Bytes;
 use super::{
     AudioInput, AudioResponseFormat, ChatCompletionFunctionCall, ChatCompletionFunctions,
     ChatCompletionNamedToolChoice, ChatCompletionRequestAssistantMessage,
-    ChatCompletionRequestFunctionMessage, ChatCompletionRequestMessage,
-    ChatCompletionRequestMessageContentPart, ChatCompletionRequestMessageContentPartImage,
+    ChatCompletionRequestAssistantMessageContent, ChatCompletionRequestFunctionMessage,
+    ChatCompletionRequestMessage, ChatCompletionRequestMessageContentPartImage,
     ChatCompletionRequestMessageContentPartText, ChatCompletionRequestSystemMessage,
-    ChatCompletionRequestToolMessage, ChatCompletionRequestUserMessage,
-    ChatCompletionRequestUserMessageContent, ChatCompletionToolChoiceOption, CreateFileRequest,
-    CreateImageEditRequest, CreateImageVariationRequest, CreateMessageRequestContent,
-    CreateSpeechResponse, CreateTranscriptionRequest, CreateTranslationRequest, DallE2ImageSize,
-    EmbeddingInput, FileInput, FilePurpose, FunctionName, Image, ImageInput, ImageModel,
-    ImageResponseFormat, ImageSize, ImageUrl, ImagesResponse, ModerationInput, Prompt, Role, Stop,
-    TimestampGranularity,
+    ChatCompletionRequestSystemMessageContent, ChatCompletionRequestToolMessage,
+    ChatCompletionRequestToolMessageContent, ChatCompletionRequestUserMessage,
+    ChatCompletionRequestUserMessageContent, ChatCompletionRequestUserMessageContentPart,
+    ChatCompletionToolChoiceOption, CreateFileRequest, CreateImageEditRequest,
+    CreateImageVariationRequest, CreateMessageRequestContent, CreateSpeechResponse,
+    CreateTranscriptionRequest, CreateTranslationRequest, DallE2ImageSize, EmbeddingInput,
+    FileInput, FilePurpose, FunctionName, Image, ImageInput, ImageModel, ImageResponseFormat,
+    ImageSize, ImageUrl, ImagesResponse, ModerationInput, Prompt, Role, Stop, TimestampGranularity,
 };
 
 /// for `impl_from!(T, Enum)`, implements
@@ -578,25 +579,63 @@ impl From<String> for ChatCompletionRequestUserMessageContent {
     }
 }
 
-impl From<Vec<ChatCompletionRequestMessageContentPart>>
+impl From<&str> for ChatCompletionRequestSystemMessageContent {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestSystemMessageContent::Text(value.into())
+    }
+}
+
+impl From<String> for ChatCompletionRequestSystemMessageContent {
+    fn from(value: String) -> Self {
+        ChatCompletionRequestSystemMessageContent::Text(value)
+    }
+}
+
+impl From<&str> for ChatCompletionRequestAssistantMessageContent {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestAssistantMessageContent::Text(value.into())
+    }
+}
+
+impl From<String> for ChatCompletionRequestAssistantMessageContent {
+    fn from(value: String) -> Self {
+        ChatCompletionRequestAssistantMessageContent::Text(value)
+    }
+}
+
+impl From<&str> for ChatCompletionRequestToolMessageContent {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestToolMessageContent::Text(value.into())
+    }
+}
+
+impl From<String> for ChatCompletionRequestToolMessageContent {
+    fn from(value: String) -> Self {
+        ChatCompletionRequestToolMessageContent::Text(value)
+    }
+}
+
+impl From<Vec<ChatCompletionRequestUserMessageContentPart>>
     for ChatCompletionRequestUserMessageContent
 {
-    fn from(value: Vec<ChatCompletionRequestMessageContentPart>) -> Self {
+    fn from(value: Vec<ChatCompletionRequestUserMessageContentPart>) -> Self {
         ChatCompletionRequestUserMessageContent::Array(value)
     }
 }
 
-impl From<ChatCompletionRequestMessageContentPartText> for ChatCompletionRequestMessageContentPart {
+impl From<ChatCompletionRequestMessageContentPartText>
+    for ChatCompletionRequestUserMessageContentPart
+{
     fn from(value: ChatCompletionRequestMessageContentPartText) -> Self {
-        ChatCompletionRequestMessageContentPart::Text(value)
+        ChatCompletionRequestUserMessageContentPart::Text(value)
     }
 }
 
 impl From<ChatCompletionRequestMessageContentPartImage>
-    for ChatCompletionRequestMessageContentPart
+    for ChatCompletionRequestUserMessageContentPart
 {
     fn from(value: ChatCompletionRequestMessageContentPartImage) -> Self {
-        ChatCompletionRequestMessageContentPart::ImageUrl(value)
+        ChatCompletionRequestUserMessageContentPart::ImageUrl(value)
     }
 }
 
@@ -654,6 +693,18 @@ impl Default for CreateMessageRequestContent {
     }
 }
 
+impl Default for ChatCompletionRequestSystemMessageContent {
+    fn default() -> Self {
+        ChatCompletionRequestSystemMessageContent::Text("".into())
+    }
+}
+
+impl Default for ChatCompletionRequestToolMessageContent {
+    fn default() -> Self {
+        ChatCompletionRequestToolMessageContent::Text("".into())
+    }
+}
+
 // start: types to multipart from
 
 #[async_convert::async_trait]

From f9193ec86ad3d391be227ba834bb47e9c52f2c52 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 23:19:39 -0700
Subject: [PATCH 15/21] udpated FunctionObject to include strict

---
 async-openai/src/types/chat.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/async-openai/src/types/chat.rs b/async-openai/src/types/chat.rs
index f5ecee92..b0545b51 100644
--- a/async-openai/src/types/chat.rs
+++ b/async-openai/src/types/chat.rs
@@ -361,6 +361,10 @@ pub struct FunctionObject {
     /// Omitting `parameters` defines a function with an empty parameter list.
     #[serde(skip_serializing_if = "Option::is_none")]
     pub parameters: Option<serde_json::Value>,
+
+    /// Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the `parameters` field. Only a subset of JSON Schema is supported when `strict` is `true`. Learn more about Structured Outputs in the [function calling guide](https://platform.openai.com/docs/guides/function-calling).
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub strict: Option<bool>,
 }
 
 #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]

From 29473533f7ce4cab6ba1ea7935c172ae2785a356 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Wed, 28 Aug 2024 23:19:58 -0700
Subject: [PATCH 16/21] update example for FunctionObject strict param

---
 examples/assistants-func-call-stream/src/main.rs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/examples/assistants-func-call-stream/src/main.rs b/examples/assistants-func-call-stream/src/main.rs
index 1a50afd9..a745292f 100644
--- a/examples/assistants-func-call-stream/src/main.rs
+++ b/examples/assistants-func-call-stream/src/main.rs
@@ -51,7 +51,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
                     },
                     "required": ["location", "unit"]
                 }
-            ))
+            )),
+            strict: None,
         }.into(),
 
         FunctionObject {
@@ -68,7 +69,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
                     },
                     "required": ["location"]
                 }
-            ))
+            )),
+            strict: None,
         }.into()
     ]).build()?;
 

From 3f261709d767bf053067214fd1c78c0310fbc3b9 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Thu, 29 Aug 2024 00:18:21 -0700
Subject: [PATCH 17/21] helper From traits for chat message types

---
 async-openai/src/types/impls.rs | 63 +++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/async-openai/src/types/impls.rs b/async-openai/src/types/impls.rs
index d4f0d0b3..81bd0fb3 100644
--- a/async-openai/src/types/impls.rs
+++ b/async-openai/src/types/impls.rs
@@ -567,6 +567,33 @@ impl From<ChatCompletionRequestToolMessage> for ChatCompletionRequestMessage {
     }
 }
 
+impl From<ChatCompletionRequestUserMessageContent> for ChatCompletionRequestUserMessage {
+    fn from(value: ChatCompletionRequestUserMessageContent) -> Self {
+        Self {
+            content: value,
+            name: None,
+        }
+    }
+}
+
+impl From<ChatCompletionRequestSystemMessageContent> for ChatCompletionRequestSystemMessage {
+    fn from(value: ChatCompletionRequestSystemMessageContent) -> Self {
+        Self {
+            content: value,
+            name: None,
+        }
+    }
+}
+
+impl From<ChatCompletionRequestAssistantMessageContent> for ChatCompletionRequestAssistantMessage {
+    fn from(value: ChatCompletionRequestAssistantMessageContent) -> Self {
+        Self {
+            content: Some(value),
+            ..Default::default()
+        }
+    }
+}
+
 impl From<&str> for ChatCompletionRequestUserMessageContent {
     fn from(value: &str) -> Self {
         ChatCompletionRequestUserMessageContent::Text(value.into())
@@ -615,6 +642,42 @@ impl From<String> for ChatCompletionRequestToolMessageContent {
     }
 }
 
+impl From<&str> for ChatCompletionRequestUserMessage {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestUserMessageContent::Text(value.into()).into()
+    }
+}
+
+impl From<String> for ChatCompletionRequestUserMessage {
+    fn from(value: String) -> Self {
+        value.as_str().into()
+    }
+}
+
+impl From<&str> for ChatCompletionRequestSystemMessage {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestSystemMessageContent::Text(value.into()).into()
+    }
+}
+
+impl From<String> for ChatCompletionRequestSystemMessage {
+    fn from(value: String) -> Self {
+        value.as_str().into()
+    }
+}
+
+impl From<&str> for ChatCompletionRequestAssistantMessage {
+    fn from(value: &str) -> Self {
+        ChatCompletionRequestAssistantMessageContent::Text(value.into()).into()
+    }
+}
+
+impl From<String> for ChatCompletionRequestAssistantMessage {
+    fn from(value: String) -> Self {
+        value.as_str().into()
+    }
+}
+
 impl From<Vec<ChatCompletionRequestUserMessageContentPart>>
     for ChatCompletionRequestUserMessageContent
 {

From 6b63466af284fcaceef3983af484cdb5b6a1ffe4 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Thu, 29 Aug 2024 00:18:36 -0700
Subject: [PATCH 18/21] Add structured-outputs example

---
 examples/structured-outputs/Cargo.toml  | 10 ++++
 examples/structured-outputs/README.md   | 37 ++++++++++++++
 examples/structured-outputs/src/main.rs | 68 +++++++++++++++++++++++++
 3 files changed, 115 insertions(+)
 create mode 100644 examples/structured-outputs/Cargo.toml
 create mode 100644 examples/structured-outputs/README.md
 create mode 100644 examples/structured-outputs/src/main.rs

diff --git a/examples/structured-outputs/Cargo.toml b/examples/structured-outputs/Cargo.toml
new file mode 100644
index 00000000..849098e4
--- /dev/null
+++ b/examples/structured-outputs/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "structured-outputs"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+async-openai = {path = "../../async-openai"}
+serde_json = "1.0.127"
+tokio = { version = "1.39.3", features = ["full"] }
diff --git a/examples/structured-outputs/README.md b/examples/structured-outputs/README.md
new file mode 100644
index 00000000..f445d4a9
--- /dev/null
+++ b/examples/structured-outputs/README.md
@@ -0,0 +1,37 @@
+## Intro
+
+Based on the 'Chain of thought' example from https://platform.openai.com/docs/guides/structured-outputs/introduction?lang=curl
+
+## Output
+
+```
+cargo run | jq .
+```
+
+```
+{
+  "final_answer": "x = -3.75",
+  "steps": [
+    {
+      "explanation": "Start with the equation given in the problem.",
+      "output": "8x + 7 = -23"
+    },
+    {
+      "explanation": "Subtract 7 from both sides to begin isolating the term with the variable x.",
+      "output": "8x + 7 - 7 = -23 - 7"
+    },
+    {
+      "explanation": "Simplify both sides. On the left-hand side, 7 - 7 equals 0, cancelling out, leaving the equation as follows.",
+      "output": "8x = -30"
+    },
+    {
+      "explanation": "Now, divide both sides by 8 to fully isolate x.",
+      "output": "8x/8 = -30/8"
+    },
+    {
+      "explanation": "Simplify the right side by performing the division. -30 divided by 8 is -3.75.",
+      "output": "x = -3.75"
+    }
+  ]
+}
+```
diff --git a/examples/structured-outputs/src/main.rs b/examples/structured-outputs/src/main.rs
new file mode 100644
index 00000000..3948308d
--- /dev/null
+++ b/examples/structured-outputs/src/main.rs
@@ -0,0 +1,68 @@
+use std::error::Error;
+
+use async_openai::{
+    types::{
+        ChatCompletionRequestSystemMessage, ChatCompletionRequestUserMessage,
+        CreateChatCompletionRequestArgs, ResponseFormat, ResponseFormatJsonSchema,
+    },
+    Client,
+};
+use serde_json::json;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+    let client = Client::new();
+
+    let schema = json!({
+      "type": "object",
+      "properties": {
+        "steps": {
+          "type": "array",
+          "items": {
+            "type": "object",
+            "properties": {
+              "explanation": { "type": "string" },
+              "output": { "type": "string" }
+            },
+            "required": ["explanation", "output"],
+            "additionalProperties": false
+          }
+        },
+        "final_answer": { "type": "string" }
+      },
+      "required": ["steps", "final_answer"],
+      "additionalProperties": false
+    });
+
+    let response_format = ResponseFormat::JsonSchema {
+        json_schema: ResponseFormatJsonSchema {
+            description: None,
+            name: "math_reasoning".into(),
+            schema: Some(schema),
+            strict: Some(true),
+        },
+    };
+
+    let request = CreateChatCompletionRequestArgs::default()
+        .max_tokens(512u32)
+        .model("gpt-4o-2024-08-06")
+        .messages([
+            ChatCompletionRequestSystemMessage::from(
+                "You are a helpful math tutor. Guide the user through the solution step by step.",
+            )
+            .into(),
+            ChatCompletionRequestUserMessage::from("how can I solve 8x + 7 = -23").into(),
+        ])
+        .response_format(response_format)
+        .build()?;
+
+    let response = client.chat().create(request).await?;
+
+    for choice in response.choices {
+        if let Some(content) = choice.message.content {
+            print!("{content}")
+        }
+    }
+
+    Ok(())
+}

From b524570337513571ebd48c30de9dfa14a454803d Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Thu, 29 Aug 2024 00:21:06 -0700
Subject: [PATCH 19/21] update readme

---
 async-openai/README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/async-openai/README.md b/async-openai/README.md
index 4ef02579..0f4b58ce 100644
--- a/async-openai/README.md
+++ b/async-openai/README.md
@@ -34,6 +34,7 @@
   - [x] Images
   - [x] Models
   - [x] Moderations
+  - [ ] Organizations | Administration
   - [ ] Uploads
 - SSE streaming on all available APIs
 - Requests (except SSE streaming) including form submissions are retried with exponential backoff when [rate limited](https://platform.openai.com/docs/guides/rate-limits).

From e7a7a0491b38d2a89d9abc3b345d7c7addbc2871 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Thu, 29 Aug 2024 00:23:41 -0700
Subject: [PATCH 20/21] updated readme

---
 async-openai/README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/async-openai/README.md b/async-openai/README.md
index 0f4b58ce..58dd5942 100644
--- a/async-openai/README.md
+++ b/async-openai/README.md
@@ -36,10 +36,10 @@
   - [x] Moderations
   - [ ] Organizations | Administration
   - [ ] Uploads
-- SSE streaming on all available APIs
+- SSE streaming on available APIs
 - Requests (except SSE streaming) including form submissions are retried with exponential backoff when [rate limited](https://platform.openai.com/docs/guides/rate-limits).
 - Ergonomic builder pattern for all request objects.
-- Microsoft Azure OpenAI Service (only APIs matching OpenAI spec)
+- Microsoft Azure OpenAI Service (only for APIs matching OpenAI spec)
 
 ## Usage
 

From 8165a8dbca6742b48c0e79fac7359e103596bae5 Mon Sep 17 00:00:00 2001
From: Himanshu Neema <himanshun.iitkgp@gmail.com>
Date: Thu, 29 Aug 2024 00:25:22 -0700
Subject: [PATCH 21/21] add comment

---
 async-openai/src/types/impls.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/async-openai/src/types/impls.rs b/async-openai/src/types/impls.rs
index 81bd0fb3..cbb7cac0 100644
--- a/async-openai/src/types/impls.rs
+++ b/async-openai/src/types/impls.rs
@@ -537,6 +537,8 @@ impl From<(String, serde_json::Value)> for ChatCompletionFunctions {
     }
 }
 
+// todo: write macro for bunch of same looking From trait implementations below
+
 impl From<ChatCompletionRequestUserMessage> for ChatCompletionRequestMessage {
     fn from(value: ChatCompletionRequestUserMessage) -> Self {
         Self::User(value)